State と \/ をブレンドする for 内包表記を構築するために、Scalaz 7 の EachT を使用しています。ここまでは順調ですね; 私は基本的に何かを得ます:
State[MyStateType, MyLeftType \/ MyRightType]
これにより、<- の左側に素敵な変数を持つ for 内包表記を作成できます。
しかし、状態アクションからタプルを返す方法がわかりません。単一の結果は問題ありません。以下のコードでは、「val 内包表記」がまさに私が望んでいることです。
しかし、タプルを返したいときはうまくいきません。「val otherComprehension」は私をさせません
(a, b) <- comprehension
\/ の左側がモノイドであることを期待しているように見えますが、その理由がわかりません。私は何が欠けていますか?
(Scalaz 7 2.0.0-SNAPSHOT、Scala 2.10.2)
object StateProblem {
case class MyStateType
case class MyRightType
case class MyLeftType
type StateWithFixedStateType[+A] = State[MyStateType, A]
type EitherTWithFailureType[F[+_], A] = EitherT[F, MyLeftType, A]
type CombinedStateAndFailure[A] = EitherTWithFailureType[StateWithFixedStateType, A]
def doSomething: CombinedStateAndFailure[MyRightType] = {
val x = State[MyStateType, MyLeftType \/ MyRightType] {
case s => (s, MyRightType().right)
}
EitherT[StateWithFixedStateType, MyLeftType, MyRightType](x)
}
val comprehension = for {
a <- doSomething
b <- doSomething
} yield (a, b)
val otherComprehension = for {
// this gets a compile error:
// could not find implicit value for parameter M: scalaz.Monoid[com.seattleglassware.StateProblem.MyLeftType]
(x, y) <- comprehension
z <- doSomething
} yield (x, y, z)
}
編集: MyLeftType がモナドであるという証拠を追加しましたが、そうではありません。私の実際のコードでは、MyLeftType はケース クラス (EarlyReturn と呼ばれます) であるため、0 を指定できますが、引数の 1 つが 0 の場合にのみ追加が機能します。
implicit val partialMonoidForEarlyReturn = new Monoid[EarlyReturn] {
case object NoOp extends EarlyReturn
def zero = NoOp
def append(a: EarlyReturn, b: => EarlyReturn) =
(a, b) match {
case (NoOp, b) => b
case (a, NoOp) => a
case _ => throw new RuntimeException("""this isnt really a Monoid, I just want to use it on the left side of a \/""")
}
}
これが良いアイデアだとは確信していませんが、問題は解決しています。