2

下面的代码有效,但选项 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)))
  }     
}
4

2 回答 2

4

使用 scalaz,您可以折叠 Option

b fold ( sb => A(sb) map (bb => C(i, some(bb))), C(i, none).success)

可能有一种简化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]
于 2012-09-07T07:07:41.550 回答
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 */ }

我不能给你确切的解决方案,因为你发布的代码不完整。Aincase class C不在范围内。这应该是一个类型参数,还是class A属于object A?

于 2012-09-07T06:30:45.953 回答