下面的代码有效但选项b上的模式匹配看起来并不优雅。 有没有办法在保持相同的语义的同时避免它?
object A {
def apply(b: B): ValidationNEL[String, A] = ...
}
case class C(i: Int, a: Option[A])
object C {
def apply(i: Int, b: Option[B]): ValidationNEL[String, C] = b match {
case None => Success(C(i, None))
case Some(sb) => A(sb).map(bb => C(i, Some(bb)))
}
}
答案 0 :(得分:4)
使用scalaz,您可以折叠选项
b fold ( sb => A(sb) map (bb => C(i, some(bb))), C(i, none).success)
可能有一种方法可以使用 pointfree样式简化sb => A(sb) map (bb => C(i, some(bb)))
,但这在scala中通常很难看:
scala> :paste
// Entering paste mode (ctrl-D to finish)
object A {
def apply(b: B): ValidationNEL[String, A] = sys.error("")
}
case class A()
case class B()
case class C(i: Int, a: Option[A])
// Exiting paste mode, now interpreting.
defined module A
defined class A
defined class B
defined class C
scala> def apply(i: Int, b: Option[B]): ValidationNEL[String, C] =
| b fold ( sb => A(sb) map (bb => C(i, some(bb))), C(i, none).success)
apply: (i: Int, b: Option[B])scalaz.Scalaz.ValidationNEL[String,C]
如果你宣布一流的功能,你就有更好的合成机会。例如:
object A { val fromB: B => ValidationNEL[String, A] = _ => sys.error("") }
object C { val fromA: Int => A => C = i => a => C(i, some(a)) }
defined module A
defined module C
然后
scala> def apply(i: Int, b: Option[B]): ValidationNEL[String, C] =
| b fold (A.fromB andThen (_ map C.fromA(i)), C(i, none).success)
apply: (i: Int, b: Option[B])scalaz.Scalaz.ValidationNEL[String,C]
答案 1 :(得分:0)
您甚至不需要scalaz特定的东西来简化这一点,只需使用Option.map
:
b.map { sb => /* will only be called if b is Some[A] */ }.getOrElse { /* will only be called if b is None */ }
我无法向您提供确切的解决方案,因为您发布的代码不完整。 A
中的case class C
不在范围内。这应该是类型参数,还是属于class A
的<{1}}?