当前位置:  开发笔记 > 编程语言 > 正文

在scala中获取和设置状态

如何解决《在scala中获取和设置状态》经验,为你挑选了1个好方法。

以下是Scala中函数式编程的一些代码:

  import State._

  case class State[S, +A](run: S => (A, S)) {
    def map[B](f: A => B): State[S, B] =
      flatMap(a => unit(f(a)))

    def map2[B, C](sb: State[S, B])(f: (A, B) => C): State[S, C] =
      flatMap(a => sb.map(b => f(a, b)))

    def flatMap[B](f: A => State[S, B]): State[S, B] = State(s => {
      val (a, s1) = run(s)
      f(a).run(s1)
    })
  }

  object State {
    type Rand[A] = State[RNG, A]

    def unit[S, A](a: A): State[S, A] =
      State(s => (a, s))

    // The idiomatic solution is expressed via foldRight
    def sequenceViaFoldRight[S, A](sas: List[State[S, A]]): State[S, List[A]] =
      sas.foldRight(unit[S, List[A]](List.empty[A]))((f, acc) => f.map2(acc)(_ :: _))

    // This implementation uses a loop internally and is the same recursion
    // pattern as a left fold. It is quite common with left folds to build
    // up a list in reverse order, then reverse it at the end.
    // (We could also use a collection.mutable.ListBuffer internally.)
    def sequence[S, A](sas: List[State[S, A]]): State[S, List[A]] = {
      def go(s: S, actions: List[State[S, A]], acc: List[A]): (List[A], S) =
        actions match {
          case Nil => (acc.reverse, s)
          case h :: t => h.run(s) match {
            case (a, s2) => go(s2, t, a :: acc)
          }
        }
      State((s: S) => go(s, sas, List()))
    }

    // We can also write the loop using a left fold. This is tail recursive like the
    // previous solution, but it reverses the list _before_ folding it instead of after.
    // You might think that this is slower than the `foldRight` solution since it
    // walks over the list twice, but it's actually faster! The `foldRight` solution
    // technically has to also walk the list twice, since it has to unravel the call
    // stack, not being tail recursive. And the call stack will be as tall as the list
    // is long.
    def sequenceViaFoldLeft[S, A](l: List[State[S, A]]): State[S, List[A]] =
      l.reverse.foldLeft(unit[S, List[A]](List()))((acc, f) => f.map2(acc)(_ :: _))

    def modify[S](f: S => S): State[S, Unit] = for {
      s <- get // Gets the current state and assigns it to `s`.
      _ <- set(f(s)) // Sets the new state to `f` applied to `s`.
    } yield ()

    def get[S]: State[S, S] = State(s => (s, s))

    def set[S](s: S): State[S, Unit] = State(_ => ((), s))
  }

我花了几个小时思考为什么getset方法看起来像他们一样,但我只是不明白.

有人可以开导我吗?



1> Filippo Vita..:

关键是在第3行:

case class State[S, +A](run: S => (A, S))

有状态计算用run函数表示.此函数表示从一个状态S到另一个状态的转换S.A是从一个状态移动到另一个状态时我们可以产生的值.

现在,我们怎样才能让国家S脱离国家一元?我们可以进行不转换到不同状态的转换,并且我们A将函数实现为状态s => (s, s):

def get[S]: State[S, S] = State(s => (s, s))

如何设置状态?我们所需要的只是一个进入状态s的函数??? => (???, s):

def set[S](s: S): State[S, Unit] = State(_ => ((), s))

编辑我想添加一个示例来查看get和执行set:

val statefullComputationsCombined = for {
  a <- State.get[Int]
  b <- State.set(10)
  c <- State.get[Int]
  d <- State.set(100)
  e <- State.get[Int]
} yield (a, c, e)

没有进一步了解这个答案,那是什么类型的statefullComputationsCombined

一定是State[S, A]对的吗?SInt什么类型但是什么A?因为我们屈服(a, c, e)必须是由步骤()的As组成的3元组.flatmap<-

我们说get"填充" A状态S所以a, c ,d类型S,所以Int.b, dUnit因为def set[S](s: S): State[S, Unit].

val statefullComputationsCombined: State[Int, (Int, Int, Int)] = for ...

要使用statefullComputationsCombined我们需要run它:

statefullComputationsCombined.run(1)._1 == (1,10,100)

如果我们想要计算结束时的状态:

statefullComputationsCombined.run(1)._2 == 100

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有