斯卡拉猫州立莫纳德

Ric*_*ing 5 scala scala-cats

我有一个类,该类具有一个参数方法,该方法可产生结果并返回与自身类似的对象,但具有更新的状态供以后使用。

例如,下面包含此类的简单示例以及如何使用它:

case class Foo(x: Double) {
  def bar(y: Double): (Foo, Double) = (Foo(x + y), x / (x + y))
}

val res = Vector(1.0,2.0,3.0,4.0).foldLeft((Foo(0), 0.0))((foo, x) => foo._1.bar(x))

res._1.bar(3.0)
Run Code Online (Sandbox Code Playgroud)

我已经看过Cats State monad,并希望我可以使用它避免使状态(“ x”成员)混乱。这里的示例接近我想要的示例但是返回新状态的函数没有任何参数,并且状态不会在类似循环的操作中传递(而是在表达式之间传递)。关于Cats,我是一个完全的新手,但是我是否吠错了树?

sla*_*vik 4

您可以在下面找到如何使 cats 状态 monad 适应您的情况的方法。List[State[S, A]]然而,我在猫的测序方面遇到了一些问题,所以我为此State[S, List[A]]编写了一个函数。sequence如果有人知道如何做到这一点,我会很感兴趣:)

import cats.data._

case class Foo(x: Double)

def bar(y: Double): State[Foo, Double] = for {
  foo <- State.get[Foo]
  _ <- State.set(Foo(foo.x + y))

} yield foo.x / (foo.x + y)

val xs: List[State[Foo, Double]] = List(1.0, 2.0, 3.0, 4.0).map(bar)

def sequence(xs: List[State[Foo, Double]]): State[Foo, List[Double]] =
  xs.foldLeft(State.pure[Foo, List[Double]](List.empty[Double])) { (acc, x) =>
    for {
      xs <- acc
      xx <- x
    } yield xx :: xs
  }

val s = sequence(xs)
val ss = s.map(_.head)

s.run(Foo(0)).value
ss.run(Foo(0)).value

ss.flatMap(_ => bar(3)).run(Foo(0)).value
Run Code Online (Sandbox Code Playgroud)

结果你得到

res0: (Foo, List[Double]) = (Foo(10.0),List(0.6, 0.5, 0.3333333333333333, 0.0))
res1: (Foo, Double) = (Foo(10.0),0.6)

res2: (Foo, Double) = (Foo(13.0),0.7692307692307693)
Run Code Online (Sandbox Code Playgroud)

  • 这是通过猫获得序列工作的一种方法:[gist](https://gist.github.com/nathaniel-may/8876978dc9275c1ee01d45b956efe7e6) (4认同)
  • 推荐的方法是将 `scalacOptions in Compile += "-Ypartial-unification"` 添加到您的构建中。 (4认同)