Seq[T => Reader[E, State[A, Unit]]] 到 Reader[E, A]
Seq[T => Reader[E, State[A, Unit]]] into Reader[E, A]
我最近问了一些问题,以找到一种聪明且可读的方法来解决这个更复杂的问题。
我需要一个带有这个签名的超级组合器:
def runStateCombinator[T, E, A](t : T, readerFactories: Seq[T => Reader[E, State[A, Unit]]], f : E => A) : Reader[E, A] = {
别担心,这只是一个需要一些依赖 (Reader
) 的状态计算 (State
)。
这是我当前的代码,欢迎任何改进(我是 scalaz n00b)。
def runStateCombinator[T, E, A](t : T, readerFactories: Seq[T => Reader[E, State[A, Unit]]], f : E => A) : Reader[E, A] = {
def transpose[E, A](readers : Seq[Reader[E, A]]) : Reader[E, Seq[A]] =
Reader { e: E => readers.map { r => r(e) } }
def map2[E, A, B](reader: Reader[E, A])(f: (E, A) => B) : Reader[E, B] =
Reader { e => f(e, reader(e)) }
val readers = readerFactories.map(_.apply(t))
val stateReader = Readers.transpose(readers).map(_.sequenceS_[A, Unit])
Readers.map2(stateReader)((ctx, state) => state.run(f(ctx))._1)
}
一般来说,monad transformers 可能是一个救世主,但在这么小的部分中,它们只能创建很多样板,尤其是在没有 kind-projector 的情况下。
更具体地说,您的 transpose
只是 sequence
的别名,在 Reader
的情况下可能需要额外的 Unapply
您的 map2
可以重构为简单的应用程序 ap
另请注意,state.run(..)._1
已经有别名 exec
我还添加了额外的 .toList
,因为 Seq
在 scalaz
中没有很好地表示
总的来说,我的简化尝试是
import scalaz._
import scalaz.syntax.traverse._
import scalaz.std.list._
import syntax.monad._
import Id.Id
type ReadState[E, A, F[_]] = Reader[E, F[State[A, Unit]]]
def runStateCombinator[T, E, A](t: T, readerFactories: Seq[T => ReadState[E, A, Id]], f: E => A): Reader[E, A] = {
val readers: ReadState[E, A, List] = readerFactories.map(_ (t)).toList.sequenceU
val stateReader = readers.map(_.sequenceS_[A, Unit])
stateReader <*> Reader(ctx => _.exec(f(ctx)))
}
例如,monad transformer 可以进行整个sequenceU.map(_.sequenceS_
单一操作而不需要明确的结果类型。
另一种选择是使用可怕的 ReaderWriterState
进行空写入:
import scalaz._
import scalaz.syntax.traverse._
import scalaz.std.list._
import Id.Id
import ReaderWriterStateT._
import scalaz.std.anyVal._
type ReadState[E, A, X] = ReaderWriterState[E, Unit, A, X]
def runStateCombinator[T, E, A](t: T, readerFactories: Seq[T => ReadState[E, A, Unit]], f: E => A): Reader[E, A] = {
val readers = readerFactories.map(_ (t)).toList
val stateReader = readers.sequence_[ReadState[E, A, ?], Unit](implicitly, rwstMonad[Id, E, Unit, A])
Reader(x => stateReader.exec(x, f(x))._2)
}
我最近问了一些问题,以找到一种聪明且可读的方法来解决这个更复杂的问题。
我需要一个带有这个签名的超级组合器:
def runStateCombinator[T, E, A](t : T, readerFactories: Seq[T => Reader[E, State[A, Unit]]], f : E => A) : Reader[E, A] = {
别担心,这只是一个需要一些依赖 (Reader
) 的状态计算 (State
)。
这是我当前的代码,欢迎任何改进(我是 scalaz n00b)。
def runStateCombinator[T, E, A](t : T, readerFactories: Seq[T => Reader[E, State[A, Unit]]], f : E => A) : Reader[E, A] = {
def transpose[E, A](readers : Seq[Reader[E, A]]) : Reader[E, Seq[A]] =
Reader { e: E => readers.map { r => r(e) } }
def map2[E, A, B](reader: Reader[E, A])(f: (E, A) => B) : Reader[E, B] =
Reader { e => f(e, reader(e)) }
val readers = readerFactories.map(_.apply(t))
val stateReader = Readers.transpose(readers).map(_.sequenceS_[A, Unit])
Readers.map2(stateReader)((ctx, state) => state.run(f(ctx))._1)
}
一般来说,monad transformers 可能是一个救世主,但在这么小的部分中,它们只能创建很多样板,尤其是在没有 kind-projector 的情况下。
更具体地说,您的 transpose
只是 sequence
的别名,在 Reader
的情况下可能需要额外的 Unapply
您的 map2
可以重构为简单的应用程序 ap
另请注意,state.run(..)._1
已经有别名 exec
我还添加了额外的 .toList
,因为 Seq
在 scalaz
总的来说,我的简化尝试是
import scalaz._
import scalaz.syntax.traverse._
import scalaz.std.list._
import syntax.monad._
import Id.Id
type ReadState[E, A, F[_]] = Reader[E, F[State[A, Unit]]]
def runStateCombinator[T, E, A](t: T, readerFactories: Seq[T => ReadState[E, A, Id]], f: E => A): Reader[E, A] = {
val readers: ReadState[E, A, List] = readerFactories.map(_ (t)).toList.sequenceU
val stateReader = readers.map(_.sequenceS_[A, Unit])
stateReader <*> Reader(ctx => _.exec(f(ctx)))
}
例如,monad transformer 可以进行整个sequenceU.map(_.sequenceS_
单一操作而不需要明确的结果类型。
另一种选择是使用可怕的 ReaderWriterState
进行空写入:
import scalaz._
import scalaz.syntax.traverse._
import scalaz.std.list._
import Id.Id
import ReaderWriterStateT._
import scalaz.std.anyVal._
type ReadState[E, A, X] = ReaderWriterState[E, Unit, A, X]
def runStateCombinator[T, E, A](t: T, readerFactories: Seq[T => ReadState[E, A, Unit]], f: E => A): Reader[E, A] = {
val readers = readerFactories.map(_ (t)).toList
val stateReader = readers.sequence_[ReadState[E, A, ?], Unit](implicitly, rwstMonad[Id, E, Unit, A])
Reader(x => stateReader.exec(x, f(x))._2)
}