Подтвердить что ты не робот

Действительно ли писатель Монада так же, как и государственная Монада?

Здесь есть отличный учебник , который, как мне кажется, предлагает мне, что Writer Monad - это, в основном, специальный корневой объект, который выполняет операции от имени (A, B), Писатель накапливает значения слева (который есть A) и что A имеет с ним соответствующий моноид (следовательно, он может накапливать или изменять состояние). Если A - это коллекция, то она накапливается.

Государственная Монада также является объектом, который имеет дело с внутренним кортежем. Они оба могут быть flatMap'd, map'd и т.д. И операции кажутся мне одинаковыми. Насколько они разные? (пожалуйста, ответьте с помощью примера scala, я не знаком с Haskel). Спасибо!

4b9b3361

Ответ 1

Ваша интуиция в том, что эти две монады тесно связаны, точно верна. Разница в том, что Writer гораздо более ограничен, поскольку он не позволяет вам читать накопленное состояние (пока вы не закончите в конце). Единственное, что вы можете сделать с состоянием в Writer, - это больше всего подходит к концу.

Более кратко, State[S, A] является своего рода оболочкой для S => (S, A), а Writer[W, A] является оберткой для (W, A).

Рассмотрим следующее использование Writer:

import scalaz._, Scalaz._

def addW(x: Int, y: Int): Writer[List[String], Int] =
  Writer(List(s"$x + $y"), x + y)

val w = for {
  a <- addW(1, 2)
  b <- addW(3, 4)
  c <- addW(a, b)
} yield c

Теперь мы можем запустить вычисление:

scala> val (log, res) = w.run
log: List[String] = List(1 + 2, 3 + 4, 3 + 7)
res: Int = 10

Мы могли бы сделать то же самое с State:

def addS(x: Int, y: Int) =
  State((log: List[String]) => (log |+| List(s"$x + $y"), x + y))

val s = for {
  a <- addS(1, 2)
  b <- addS(3, 4)
  c <- addS(a, b)
} yield c

И затем:

scala> val (log, res) = s.run(Nil)
log: List[String] = List(1 + 2, 3 + 4, 3 + 7)
res: Int = 10

Но это немного более многословно, и мы могли бы сделать много других вещей с State, что мы не могли бы сделать с Writer.

Итак, мораль этой истории заключается в том, что вы должны использовать Writer, когда можете, - ваше решение будет более чистым, более кратким, и вы получите удовлетворение от использования соответствующей абстракции.

Очень часто Writer не даст вам всю необходимую вам мощность, и в этих случаях State будет ждать вас.

Ответ 2

tl; dr State - это чтение и запись, в то время как Writer - это просто запись.

С состоянием вы имеете доступ к предыдущим сохраненным данным, и вы можете использовать эти данные в своем текущем вычислении:

def myComputation(x: A) =
  State((myState: List[A]) => {
        val newValue = calculateNewValueBasedOnState(x,myState)
        (log |+| List(newValue), newValue)
  })

С Writer вы можете хранить данные в каком-либо объекте, к которому у вас нет доступа, вы можете писать только на этот объект.