gpt4 book ai didi

scala - 在 Scala 中编写 state monad

转载 作者:行者123 更新时间:2023-12-04 09:30:55 25 4
gpt4 key购买 nike

我从 Philip Wadler 的函数式编程的 Monads 中借用了状态 monad 的理论:

type M a = State → (a, State) 
type State = Int
unit :: a → M a
unit a = λx. (a, x)
(*) :: M a → (a → M b) → M b
m * k = λx.
let (a, y) = m x in
let (b, z) = k a y in
(b, z)
我想使用状态 monad 的方式如下:

Given a list L I want different parts of my code to get this list and update this list by adding new elements at its end.


我想上面会修改为:
type M = State → (List[Data], State) 
type State = List[Data]
def unit(a: List[Data]) = (x: State) => (a,x)
def star(m: M, k: List[Data] => M): M = {
(x: M) =>
val (a,y) = m(x)
val (b,z) = k(a)(y)
(b,z)
}
def get = ???
def update = ???
我如何填写详细信息,即?
  • 如何实例化我的层次结构以处理具体列表?
  • 如何根据上述内容实现获取和更新?

  • 最后,我将如何使用带有 flatMap 和 unit 的 Scala 语法来做到这一点?

    最佳答案

    您的 M定义不正确。应该花a/A作为参数,像这样:

    type M[A] = State => (A, State)
    您还在其他地方错过了该类型参数。 unit应该有这样的签名:
    def unit[A](a: A): M[A]
    star应该有这样的签名:
    def star[A, B](m: M[A], k: A => M[B]): M[B]
    希望这使功能更加清晰。
    您对 unit 的实现几乎一样:
    def unit[A](a: A): M[A] = x => (a, x)
    然而,在 star ,您的 lambda ( x ) 的参数类型为 State ,不是 M , 因为 M[B]基本上是 State => (A, State) .剩下的你做对了:
    def star[A, B](m: M[A])(k: A => M[B]): M[B] = 
    (x: State) => {
    val (a, y) = m(x)
    val (b, z) = k(a)(y)
    (b, z)
    }

    编辑:根据@Luis Miguel Mejia Suarez:

    It would probably be easier to implement if you make your State a class and define flatMap inside it. And you can define unit in the companion object.


    他建议 final class State[S, A](val run: S => (A, S)) ,这也将允许您使用中缀函数,如 >>= .
    另一种方法是定义 State作为函数的类型别名 S => (A, S)并使用隐式类扩展它。
    type State[S, A] = S => (A, S)
    object State {
    //This is basically "return"
    def unit[S, A](a: A): State[S, A] = s => (a, s)
    }

    implicit class StateOps[S, A](private runState: S => (A, S)) {
    //You can rename this to ">>=" or "flatMap"
    def *[B](k: A => State[S, B]): State[S, B] = s => {
    val (a, s2) = runState(s)
    k(a)(s2)
    }
    }
    如果您对 get 的定义是

    set the result value to the state and leave the state unchanged(borrowed from Haskell Wiki), then you can implement it like this:

    def get[S]: State[S, S] = s => (s, s)
    如果您的意思是要提取状态(在本例中为 List[Data] ),您可以使用 execState (在 StateOps 中定义):
    def execState(s: S): S = runState(s)._2

    这是一个糟糕的例子,说明如何向 List 添加元素.
    def addToList(n: Int)(list: List[Int]): ((), List[Int]) = ((), n :: list)

    def fillList(n: Int): State[List[Int], ()] =
    n match {
    case 0 => s => ((), s)
    case n => fillList(n - 1) * (_ => addToList(n))
    }
    println(fillList(10)(List.empty))给我们这个(第二个元素可以用 execState 提取):
    ((),List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))

    关于scala - 在 Scala 中编写 state monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62849571/

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