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

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

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

2 ответа

Решение

Ваша интуиция о том, что эти две монады тесно связаны, абсолютно верна. Разница в том, что 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 буду ждать тебя.

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

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

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

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

Другие вопросы по тегам