gpt4 book ai didi

scala - 在scalaz中将状态分层

转载 作者:行者123 更新时间:2023-12-03 12:20:20 24 4
gpt4 key购买 nike

Integrating State with Either(幻灯片88)中,给定StateEither下分层的模式,是否有建议的方法来添加另一种状态,例如通过Writer之类的日志记录?为了利用StateEither的快速失败行为,新状态似乎必须存在于现有EitherflatMap之间。

以下是演示文稿中的代码的可运行示例,已调整为在Scalaz 7.2.8上的2.11.8上运行。有没有一种方法可以在现有行为的基础上干净地添加新的monad转换器,从而简化重构? Stacking StateT in Scalaz适用于堆叠,但不能解决flatMap的快速失败Either行为所造成的排序问题。

// Based on slide 88+ in https://speakerdeck.com/mpilquist/scalaz-state-monad
// Adjusted for Scala 2.11 (invariant A), Scalaz 7.2 (Pointed->Applicative) and Throwable on lhs of Either
object IntegratingStateAndEither {
import scalaz._
import scalaz.Scalaz._
import EitherT._
import scalaz.StateT.stateMonad

type QueryStateS[A] = State[QueryState, A]
type ET[F[_], A] = EitherT[F, Throwable, A]
type QueryStateES[A] = ET[QueryStateS, A]

object QueryStateES {
def apply[A](s: QueryStateS[Throwable \/ A]): QueryStateES[A] = EitherT(s)
def liftE[A](e: Throwable \/ A): QueryStateES[A] = apply(Applicative[QueryStateS].point(e))
def liftS[A](s: QueryStateS[A]): QueryStateES[A] = MonadTrans[ET].liftM(s)
}

def runQuery(s: String, m: Model): QueryStateES[QueryResult] = for {
query <- parseQuery(s)
res <- performQuery(query, m)
} yield res

def parseQuery(s: String): QueryStateES[StatsQuery] =
QueryStateES.liftE(new Exception("TODO parse").left)

def performQuery(q: StatsQuery, m: Model): QueryStateES[QueryResult] =
QueryStateES.liftE(new Exception("TODO perform").left)

// Just examples that do nothing
case class Model()
case class StatsQuery()
case class QueryResult()
case class QueryState()

def test = runQuery("a + b", Model()).run.run(QueryState())
}

最佳答案

要回答有关日志记录的特定示例,可以执行以下操作:

object LayeringReaderWriterStateWithEither {
// Based on slide 88+ in https://speakerdeck.com/mpilquist/scalaz-state-monad
// Adjusted for Scala 2.11 (invariant A), Scalaz 7.2 (Pointed->Applicative) and Throwable on lhs of Either
object IntegratingStateAndEither {
import scalaz._
import scalaz.Scalaz._
import EitherT._

type QueryStateS[A] = ReaderWriterState[List[String], String, QueryState, A]
type ET[F[_], A] = EitherT[F, Throwable, A]
type QueryStateES[A] = ET[QueryStateS, A]

object QueryStateES {
def apply[A](s: QueryStateS[Throwable \/ A]): QueryStateES[A] = EitherT(s)
def liftE[A](e: Throwable \/ A): QueryStateES[A] = apply(Applicative[QueryStateS].point(e))
def liftS[A](s: QueryStateS[A]): QueryStateES[A] = MonadTrans[ET].liftM(s)
def log(msg: String): QueryStateES[Unit] = liftS {
ReaderWriterState[List[String], String, QueryState, Unit] {
case (r, s) => (msg.format(r, s), (), s).point[Id]
}
}
}

def runQuery(s: String, m: Model): QueryStateES[QueryResult] = for {
_ ← log("Starting")
query <- parseQuery(s)
_ ← log(s"Got a query: $query")
res <- performQuery(query, m)
} yield res

def log(msg: String): QueryStateES[Unit] =
QueryStateES.log(msg)

def parseQuery(s: String): QueryStateES[StatsQuery] =
QueryStateES.liftE(new Exception(s"TODO parse $s").left)

def performQuery(q: StatsQuery, m: Model): QueryStateES[QueryResult] =
QueryStateES.liftE(new Exception(s"TODO perform $q in $m").left)

// Just examples that do nothing
case class Model()
case class StatsQuery()
case class QueryResult()
case class QueryState()

def test = runQuery("a + b", Model()).run.run(Nil, QueryState())
}
}

关于scala - 在scalaz中将状态分层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41536037/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com