【问题标题】:How to combine Reader and State monad如何结合 Reader 和 State monad
【发布时间】:2015-11-29 23:07:44
【问题描述】:

我正在尝试将 Reader monad 与 State monad 结合起来。 这是我的代码:

object StatePoc extends App {
  def startsWithState : Reader[String, State[Seq[String], Unit]] = Reader { s => State { ss => (ss.filter(_.startsWith(s)), Unit)}}
  def endsWithState : Reader[String, State[Seq[String], Unit]] = Reader { s => State { ss => (ss.filter(_.endsWith(s)), Unit)}}
  def process: Kleisli[Id.Id, String, State[Seq[String], Unit]] = {
    for {
      s <- startsWithState
      e <- endsWithState
    } yield e
  }

  val all = Seq("AB", "BA", "ABA", "ABBA")

  println(process("A")(all))
}

不幸的是,这段代码没有返回预期的结果:List(BA, ABA, ABBA) 而不是List(ABA, ABBA)

【问题讨论】:

    标签: scala monads scalaz


    【解决方案1】:

    在您的函数process 中,您从两个读者那里读取了状态对象,但您只返回了最后一个状态对象,而不是两者的组合。像这样的东西会结合se

      def process: Kleisli[Id.Id, String, State[Seq[String], Unit]] = {
        for {
          s <- startsWithState
          e <- endsWithState
        } yield {
          State { seq => e.run(s.run(seq)._1)}
        }
      }
    

    【讨论】:

    • 谢谢。使用嵌套的 for comp 还可以改进 def process = { for { s
    【解决方案2】:

    另一个救星可能是 monad 转换器,它需要一些样板,尤其是没有 kind-projector:

    type StringReader[a] = Reader[String, a]
    type StateChoose[a, b] = StateT[StringReader, a, b]
    type StringsChoose[a] = StateChoose[Seq[String], a]
    type StringsTrans[m[_], b] = StateT[m, Seq[String], b]
    
    def ST = MonadState[StateChoose, Seq[String]]
    def R = MonadReader[Reader, String]
    def T = MonadTrans[StringsTrans]
    
    def transform(action: String => Seq[String] => Seq[String]): StringsChoose[Unit] = for {
      s <- T.liftMU(R.ask)
      _ <- ST.modify(action(s))
    } yield ()
    def startsWithState = transform( s => _.filter(_.startsWith(s)))
    def endsWithState = transform(s => _.filter(_.endsWith(s)))
    
    def process: StringsChoose[Unit] = {
      for {
        s <- startsWithState
        e <- endsWithState
      } yield e
    }
    val all = Seq("AB", "BA", "ABA", "ABBA")
    
    println(process.exec(all).apply("A"))
    

    【讨论】:

      猜你喜欢
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      • 2014-03-22
      • 1970-01-01
      • 2017-06-22
      • 1970-01-01
      • 2014-11-14
      • 1970-01-01
      相关资源
      最近更新 更多