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]

2 番目の実装

ファーストクラスの関数を宣言すると、合成の可能性が高くなります。例えば:

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 */ }

投稿したコードが完全ではないため、正確な解決策を提供できません。Ainはcase class C対象外です。これは型パラメーターである必要がありますか、それともclass Aに属していobject Aますか?

于 2012-09-07T06:30:45.953 に答える