Seq [T =>读者[E,国家[A,单位]]进入读者[E,A]

时间:2015-11-30 22:42:10

标签: scala scalaz

我最近提出了一些问题,要求找到一种智能且易读的方法来解决这个更复杂的问题。

我需要一个带有此签名的超级组合器:

def runStateCombinator[T, E, A](t : T, readerFactories: Seq[T => Reader[E, State[A, Unit]]], f : E => A) : Reader[E, A] = {

别担心,这只是一个有状态的计算(State)需要一些代表(Reader)。

这是我目前的代码,任何改进都非常受欢迎(我是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)
  }

1 个答案:

答案 0 :(得分:1)

一般来说,monad变形金刚可能是一个救世主,但在如此小的一块中,它们只能创造出大量的样板,尤其是没有善良的投影仪。

更具体地说,您的transpose只是sequence的别名,Unapply可能需要额外的Reader 您的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 trasformer可以进行整个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)
}