Scala (scalaz) State monad - 映射 Option 状态类型
Scala (scalaz) State monad - map over Option state type
如何申请实现以下功能?
def wrapIntoOption(state: State[S, A]): State[Option[S], Option[A]]
大图是这样的:
case class Engine(cylinders: Int)
case class Car(engineOpt: Option[Engine])
val engineOptLens = Lens.lensu((c, e) => c.copy(engineOpt = e), _.engineOpt)
def setEngineCylinders(count: Int): State[Engine, Int] = State { engine =>
(engine.copy(cylinders = count), engine.cylinders)
}
def setEngineOptCylinders(count: Int): State[Option[Engine], Option[Int]] = {
??? // how to reuse setEngineCylinders?
}
def setCarCylinders(count: Int): State[Car, Option[Int]] = {
engineOptLens.lifts(setEngineOptCylinders)
}
有没有更好的方法来处理选项属性?
创建 wrapIntoOption
函数的一种方法是在传递的 State[S, A]
上调用 run
并将生成的 (S, A)
元组转换为 (Option[S], Option[A])
。
import scalaz.State
import scalaz.std.option._
import scalaz.syntax.std.option._
def wrapIntoOption[S, A](state: State[S, A]): State[Option[S], Option[A]] =
State(_.fold((none[S], none[A])){ oldState =>
val (newState, result) = state.run(oldState)
(newState.some, result.some)
})
然后您可以将 setEngineOptCylinders
定义为:
def setEngineOptCylinders(count: Int): State[Option[Engine], Option[Int]] =
wrapIntoOption(setEngineCylinders(count))
您可以将其用作:
scala> val (newEngine, oldCylinders) = setEngineOptCylinders(8).run(Engine(6).some)
newEngine: Option[Engine] = Some(Engine(8))
oldCylinders: Option[Int] = Some(6)
如何申请实现以下功能?
def wrapIntoOption(state: State[S, A]): State[Option[S], Option[A]]
大图是这样的:
case class Engine(cylinders: Int)
case class Car(engineOpt: Option[Engine])
val engineOptLens = Lens.lensu((c, e) => c.copy(engineOpt = e), _.engineOpt)
def setEngineCylinders(count: Int): State[Engine, Int] = State { engine =>
(engine.copy(cylinders = count), engine.cylinders)
}
def setEngineOptCylinders(count: Int): State[Option[Engine], Option[Int]] = {
??? // how to reuse setEngineCylinders?
}
def setCarCylinders(count: Int): State[Car, Option[Int]] = {
engineOptLens.lifts(setEngineOptCylinders)
}
有没有更好的方法来处理选项属性?
创建 wrapIntoOption
函数的一种方法是在传递的 State[S, A]
上调用 run
并将生成的 (S, A)
元组转换为 (Option[S], Option[A])
。
import scalaz.State
import scalaz.std.option._
import scalaz.syntax.std.option._
def wrapIntoOption[S, A](state: State[S, A]): State[Option[S], Option[A]] =
State(_.fold((none[S], none[A])){ oldState =>
val (newState, result) = state.run(oldState)
(newState.some, result.some)
})
然后您可以将 setEngineOptCylinders
定义为:
def setEngineOptCylinders(count: Int): State[Option[Engine], Option[Int]] =
wrapIntoOption(setEngineCylinders(count))
您可以将其用作:
scala> val (newEngine, oldCylinders) = setEngineOptCylinders(8).run(Engine(6).some)
newEngine: Option[Engine] = Some(Engine(8))
oldCylinders: Option[Int] = Some(6)