我正在尝试将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)
。
答案 0 :(得分:4)
在你的函数process
中,你从两个读者中读取状态对象,但是你只返回最后一个状态对象,而不是两者的组合。这样的事情会同时结合s
和e
:
def process: Kleisli[Id.Id, String, State[Seq[String], Unit]] = {
for {
s <- startsWithState
e <- endsWithState
} yield {
State { seq => e.run(s.run(seq)._1)}
}
}
答案 1 :(得分:2)
另一个救世主可能是monad变压器,这需要一些样板,特别是没有种类的投影仪:
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"))