最小的Scala monad包含好的值或错误消息?

时间:2014-04-28 18:20:15

标签: scala monads

在Scala中,我想的是一个简单的monad Result,它包含Good值或Error消息。这是我的实施。

我想问:我是否以过于复杂的方式做某事?或甚至错误?

这可以简化(但保持可读性,所以没有Perl golf)?例如,我是否需要使用抽象类和伴随对象,或者将所有内容放在普通类中是否更简单?

abstract class Result[+T] {
  def flatMap[U](f: T => Result[U]): Result[U] = this match {
    case Good(x) => f(x)
    case e: Error => e
  }
  def map[U](f: T => U): Result[U] = flatMap { (x: T) => Result(f(x)) }
}
case class Good[T](x: T) extends Result[T]
case class Error(e: String) extends Result[Nothing]
object Result { def apply[T](x: T): Result[T] = Good(x) }

现在,如果我,例如

val x = Good(5)
def f1(v: Int): Result[Int] = Good(v + 1)
def fE(v: Int): Result[Int] = Error("foo")

然后我可以用通常的方式链接:

x flatMap f1 flatMap f1    // => Good(7)
x flatMap fE flatMap f1    // => Error(foo)

和理解:

for (
  a <- x;
  b <- f1(a);
  c <- f1(b)
) yield c    // => Good(7)

P.S:我知道Scalaz中的\/ monad,但这是出于安装和导入Scalaz感觉有点沉重的简单情况。

1 个答案:

答案 0 :(得分:1)

对我来说很好看。我会将abstract class更改为sealed trait。我认为您可以省略flatMapmap的返回类型,而不会失去任何可读性。

我喜欢伴侣对象,因为它会调出你的单位函数。