给出以下类型:
sealed trait Pet {
val name: String
}
case class Dog(override val name: String) extends Pet
case class Cat(override val name: String) extends Pet
sealed trait Error
case object DBConnection extends Error
case object NoResults extends Error
Run Code Online (Sandbox Code Playgroud)
我们编写了一个按名称搜索宠物的函数.
def foo(petName: String): Either[Error, Pet] = {
val results: Either[Error, List[Pet]] = ??? // does not matter
val foundPet: Option[Pet] = results match {
case left @ Left(_) => None
case Right(ps) => ps.find(_.name == petName)
}
foundPet match {
case None => Left(NoResults)
case Some(p) => Right(p)
}
}
Run Code Online (Sandbox Code Playgroud)
请忽略有关数据库调用的上述代码的任何改进.
理想情况下,我更喜欢将上面的代码写成一个简单的for comprehension
,利用Either
monad.我相信,模式匹配很容易阅读,但for
我怀疑,替代方案会更简洁.
如何用for-comprehension重写上面的代码?我想我可以制作匹配返回类型的方法Either[Error, Pet]
,但不确定.
问题是Scala Either
不是monad并且它没有偏见因此你不能在for-comprehension中使用它:你必须首先得到一个LeftProject或RightProjection,就像其他海报一样.
如果你开放的话scalaz
.scalaz disjunction
(\/
)是正确的偏见并遵循所有monad法则.当你map
超过它它给你right
价值.
所以你的类型将成为
val results : \/[Error,List[Pet]]
Run Code Online (Sandbox Code Playgroud)
并且 results.map
会给你List[Pet]
因为斯卡拉兹分离是正确的偏见.
这可能也有帮助
归档时间: |
|
查看次数: |
500 次 |
最近记录: |