Scala Cats Государственная Монада - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть класс, который имеет метод с одним параметром, который производит результат и возвращает объект, подобный самому себе, но с обновленным состоянием для последующего использования.

Например, ниже приведен простой пример такого класса икак я могу это использовать:

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)

Я посмотрел на монаду Cats State и надеялся, что смогу использовать ее, чтобы избежать переполнения состояния (член "x").Примеры здесь близки к тому, что я хочу, но функция, которая возвращает новое состояние, не имеет никаких параметров, и состояние не передается в циклической операции (вместо этого оно передается между выражениями).Я абсолютный новичок, когда дело доходит до кошек, но я лаю не на том дереве?

1 Ответ

0 голосов
/ 20 декабря 2018

Ниже вы можете найти способ адаптации монады состояния кошки к вашему случаю.Однако у меня были некоторые проблемы с секвенированием 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

В результате вы получите

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)
...