2013-04-21 2 views
3

я кодирование для понимания, и спрашиваю что-то:Либо, Опция и для постижений

def updateUserStats(user: User): Either[Error,User] = for { 
    stampleCount <- stampleRepository.getStampleCount(user).right 
    userUpdated <- Right(copyUserWithStats(user,stampleCount)).right // ????????? 
    userSaved <- userService.update(userUpdated).right 
} yield userSaved 


def copyUserWithStats(user: User, stamples: Long): User = { 
    val newStats = user.userStats.copy(stamples = stamples) 
    user.copy(userStats = newStats) 
} 

Кажется, используя copyUserWithStats, который не возвращает либо не может быть использован непосредственно в для понимания, потому что это не имеет методов map/flatMap.

Так интересно, в этом случае, является подходящим решением для использования Right(copyUserWithStats(user,stampleCount)).right

Это, кажется, работает, по крайней мере ...

Кстати, я также попытался с опцией, но Бесполезный» t, может кто-нибудь объяснить почему?

def updateUserStats(user: User): Either[Error,User] = for { 
    stampleCount <- stampleRepository.getStampleCount(user).right 
    userUpdated <- Some(copyUserWithStats(user,stampleCount)) 
    userSaved <- userService.update(userUpdated).right 
} yield userSaved 

Благодаря

ответ

7

В для-понимания все монады должны быть одного и того же рода. Это означает, что вы не можете смешивать RightProjection и Option, так как выход должен быть Either. Это связано с тем, что for-comprehension переводится в вложенную конструкцию flatMap/map. Ваш пример будет выглядеть следующим образом:

def updateUserStats(user: User): Either[Error,User] = 
    stampleRepository.getStampleCount(user).right.flatMap { stampleCount => 
    Some(copyUserWithStats(user,stampleCount)).flatMap { userUpdated => 
     userService.update(userUpdated).right.map { userSaved => 
     userSaved 
     } 
    } 
    } 

Если мы теперь посмотрим на подписи RightProjection.flatMap, которая Защита flatMap[AA >: A, Y](f: (B) ⇒ Either[AA, Y]): Either[AA, Y], мы видим, что результат должен быть Either, но flatMap из Option имеют подпись flatMap[B](f: (A) ⇒ Option[B]): Option[B] , Он возвращает Option и нет разумного способа перевести Option на номер Either.

редактировать: Следующий пример не тихую работу для Either, смотрите ссылку на huynhjl для получения дополнительной информации

Однако вы можете, кроме извлечения значений из монад в наличии для понимания и создания переменных, так что ваш пример может быть переписана как:

def updateUserStats(user: User): Either[Error,User] = for { 
    stampleCount <- stampleRepository.getStampleCount(user).right 
    userUpdated = copyUserWithStats(user,stampleCount) 
    userSaved <- userService.update(userUpdated).right 
} yield userSaved 

, что избавляет нас от ненужного распределения, а также делает код более удобочитаемым.

+0

Вы пытались создать такие переменные? Это не работает для меня с «Либо». – huynhjl

+0

http://stackoverflow.com/questions/10688447/scala-either-rightprojection-confusion-for-comprehension-de-sugaring – huynhjl

+0

Thanks huynhjl. Честно говоря, я просто ожидал, что это сработает и не пробовал. – drexin

Смежные вопросы