gpt4 book ai didi

scala - 具有无形状态单子(monad)的状态转换

转载 作者:行者123 更新时间:2023-12-04 11:35:47 26 4
gpt4 key购买 nike

Scalaz State monad 的 modify 具有以下签名:

def modify[S](f: S => S): State[S, Unit]

这允许将状态替换为相同类型的状态,这在状态包含无形值(例如 Record)时效果不佳。其类型随着新字段的添加而改变。在这种情况下,我们需要的是:

def modify[S, T](f: S => T): State[T, Unit]

什么是调整 Scalaz 的 State monad 以使用无形状态的好方法,以便人们可以使用 Records 而不是可怕的 Map[String, Any] ?

例子:

case class S[L <: HList](total: Int, scratch: L)

def contrivedAdd[L <: HList](n: Int): State[S[L], Int] =
for {
a <- init
_ <- modify(s => S(s.total + n, ('latestAddend ->> n) :: s.scratch))
r <- get
} yield r.total

更新:

Travis 答案的完整代码是 here .

最佳答案

State是更通用类型的类型别名 IndexedStateT专门设计用于将更改状态类型的函数表示为状态计算:

type StateT[F[_], S, A] = IndexedStateT[F, S, S, A]
type State[S, A] = StateT[Id, S, A]

虽然不可能写出你的 modify[S, T]使用 State , IndexedState 是可能的(这是 IndexedStateT 的另一个类型别名,将效果类型固定为 Id ):
import scalaz._, Scalaz._

def transform[S, T](f: S => T): IndexedState[S, T, Unit] =
IndexedState(s => (f(s), ()))

您甚至可以在 for 中使用它- 理解(这对我来说总是有点奇怪,因为单子(monad)类型在操作之间发生变化,但它有效):
val s = for {
a <- init[Int];
_ <- transform[Int, Double](_.toDouble)
_ <- transform[Double, String](_.toString)
r <- get
} yield r * a

进而:
scala> s(5)
res5: scalaz.Id.Id[(String, String)] = (5.0,5.05.05.05.05.0)

在您的情况下,您可能会编写如下内容:
import shapeless._, shapeless.labelled.{ FieldType, field }

case class S[L <: HList](total: Int, scratch: L)

def addField[K <: Symbol, A, L <: HList](k: Witness.Aux[K], a: A)(
f: Int => Int
): IndexedState[S[L], S[FieldType[K, A] :: L], Unit] =
IndexedState(s => (S(f(s.total), field[K](a) :: s.scratch), ()))

进而:
def contrivedAdd[L <: HList](n: Int) = for {
a <- init[S[L]]
_ <- addField('latestAdded, n)(_ + n)
r <- get
} yield r.total

(这可能不是分解更新操作的最佳方法,但它显示了基本思想是如何工作的。)

还值得注意的是,如果您不关心将状态转换表示为状态计算,则可以使用 imap在任何旧的 State :
init[S[HNil]].imap(s =>
S(1, field[Witness.`'latestAdded`.T](1) :: s.scratch)
)

这不允许您以相同的方式组合使用这些操作,但在某些情况下它可能就是您所需要的。

关于scala - 具有无形状态单子(monad)的状态转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34870889/

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