重写模式匹配与理解

Kev*_*ith 3 monads scala

给出以下类型:

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,利用Eithermonad.我相信,模式匹配很容易阅读,但for我怀疑,替代方案会更简洁.

如何用for-comprehension重写上面的代码?我想我可以制作匹配返回类型的方法Either[Error, Pet],但不确定.

Vik*_*dya 6

问题是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]因为斯卡拉兹分离是正确的偏见.

可能也有帮助