Я использую Scalaz 7 EitherT для создания for-computing, которые смешивают State и \ /. Все идет нормально; Я получаю то, что в основном:
State[MyStateType, MyLeftType \/ MyRightType]
и это позволяет мне создавать для понимания, у которых есть хорошие переменные в левой части ‹-.
Но я не могу понять, как вернуть кортежи из действия состояния. Одиночные результаты просто прекрасны - в приведенном ниже коде "val computing" - именно то, что я хочу добиться.
Но все разваливается, когда я хочу вернуть кортеж; "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 - это класс case (называемый EarlyReturn), поэтому я могу указать ноль, но добавление работает только в том случае, если один из аргументов равен нулю:
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 \/""")
}
}
Я не уверен, что это хорошая идея, но она решает проблему.
for
-понимание здесь - см. этот вопрос для упрощенной версии. того же выпуска. - person Travis Brown   schedule 02.07.2013EitherT
(или\/
) требуется экземпляр моноида для левой стороны, и по какой-то причине 2.10.2 придерживается операции фильтрации в этомfor
-понимании. - person Travis Brown   schedule 02.07.2013