Что такое монада-трансформер в отличие от монады?

вопрос говорит все это, на самом деле. Я знаю (Scala)монады выглядит так:

trait Monad[M[_]] {
  def pure[A](a : A) : M[A]
  def bind[A, B](ma : M[A], f : A => M[B]) : M[B]
}

что делает Монада трансформатор выглядеть? И для чего они используются?


редактировать. рассмотрим следующий сеанс REPL: если трансформатор монады каким-то образом украшает монаду возможностями чтения (или наоборот)

допустим, я просто хочу использовать replicateM от Scalaz;

scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._

scala> some(4).replicateM[List](2)
res20: Option[List[Int]] = Some(List(4, 4))

теперь допустим, вместо Option[Int], мне нужно прочитать Int значение File:

scala> val f = (_ : java.io.File) => some(1)
f: (java.io.File) => Option[Int] = <function1>

Итак, я могу лечить это читатель, как будто это была Монада?

scala> ReaderT(f).replicateM[List](2)
<console>:16: error: value replicateM is not a member of scalaz.ReaderT[Option,java.io.File,Int]
       ReaderT(f).replicateM[List](2)
                  ^

Err, нет.

извинения, если все это кажется глупым, я просто пытаюсь понять, какая прекрасная доброта моя упаковка File => Option[Int] на ReaderT на самом деле может купить меня.

3 ответов


трансформаторы монады-это функции типа, которые при применении к типу монады генерируют новую монаду, которая сочетает в себе поведение обоих компонентов.

Е. Г. в xmonad диспетчер окон, вычисления выполняются внутри:

newtype X a = X (ReaderT XConf (StateT XState IO) a)

то есть a Reader состоит с State и IO монады.

  • Reader дает доступ к памяти только для чтения
  • State обеспечивает форму состояния чтения-записи
  • IO позволяет произвольные внешние эффекты

обратите внимание, что преобразования монады, таким образом, являются типами более высокого ранга. Они принимают монадический тип рода (* -> *), и дать новый тип такого рода.

как всегда, Haskell wiki имеет полезный контент:

где все это начал:


трансформаторы монады использованы для совмещать / удлиняя монады (добавьте возможности одной монады к другим). Е. Г., ReaderT (читатель трансформатор) обогащает данную монаду M С Reader возможности (превращает данную монаду в читателя, сохраняя оригинальные функции M).

в то же время трансформаторы монады являются нормальными монадами, которые имеют bind, return и другие операции.

вы можете найти примеры трансформаторов монады в Scalaz - например,читатель и государство монады.


Я не думаю, что Reader предназначен для чтения значений из файла. Уверен, что это для чтения значений конфигурации. Я думаю об этом как об альтернативе глобальным переменным, статике или динамическим/локальным переменным (называемым "специальными переменными" в Common Lisp или иногда переменными fluide в схеме с "fluid-let"). Таким образом, используйте Reader / ReaderT вместо доступа к глобальной или динамической переменной и вместо передачи параметров в каждый из ваших методов, которые могут потребовать доступа к некоторой конфигурации выбор. Это может быть полезно, когда какой-то очень глубокий фрагмент кода внезапно требует доступа к новой опции конфигурации. Вы можете передать опцию из функции main (), незаметно получить доступ к глобальному или использовать Reader/ReaderT.