在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感觉有点沉重的简单情况。
答案 0 :(得分:1)
对我来说很好看。我会将abstract class
更改为sealed trait
。我认为您可以省略flatMap
和map
的返回类型,而不会失去任何可读性。
我喜欢伴侣对象,因为它会调出你的单位函数。