scala - monadas - ¿Qué es un transformador de mónada distinto de una mónada?
monads (3)
La pregunta lo dice todo, de verdad. Sé que (Scala) Monad se ve así:
trait Monad[M[_]] {
def pure[A](a : A) : M[A]
def bind[A, B](ma : M[A], f : A => M[B]) : M[B]
}
¿Cómo se ve un Monad Transformer ? Y para qué se usan?
EDITAR Considere la siguiente sesión de REPL: si un transformador de mónada de alguna manera decora una mónada con capacidades de lector (o viceversa) Digamos que solo quiero usar replicateM
de Scalaz ;
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> some(4).replicateM[List](2)
res20: Option[List[Int]] = Some(List(4, 4))
Ahora digamos que, en lugar de tener una Option[Int]
, necesito leer un valor Int
de un File
:
scala> val f = (_ : java.io.File) => some(1)
f: (java.io.File) => Option[Int] = <function1>
Entonces, ¿puedo tratar a este lector como si fuera una Mónada?
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, no.
Disculpas si todo esto parece estúpido, solo estoy tratando de comprender qué bondad tan maravillosa mi envoltura de File => Option[Int]
en un ReaderT
realmente me puede comprar.
Los transformadores de mónada se usan para combinar / ampliar mónadas (agregar capacidades de una mónada a otra). Por ejemplo, ReaderT
(Reader Transformer) enriquece la monad M
dada con las capacidades de Reader
(transforma la mónada dada en Reader conservando las características originales de M
).
Al mismo tiempo, los transformadores de mónada son mónadas normales que tienen operaciones de bind
, return
y otras.
Puede encontrar ejemplos de transformadores de mónada en Scalaz , por ejemplo, para mónadas Reader y State .
No creo que Reader sea para leer valores de un archivo. Bastante seguro es para leer valores de configuración. Lo considero una alternativa a las variables globales, estáticas o variables dinámicas / locales de subprocesos (llamadas "variables especiales" en Common Lisp o, a veces, variables fluideas en Scheme con su "fluido-let"). Por lo tanto, use Reader / ReaderT en lugar de acceder a una variable global o dinámica y en lugar de pasar parámetros a cada uno de sus métodos que pueden requerir acceso a alguna opción de configuración. Esto puede ser útil cuando una parte muy profunda del código de repente requiere acceso a una nueva opción de configuración. Puede pasar la opción hacia abajo desde su función principal (), acceder furtivamente a un servidor global o usar Reader / ReaderT.
Los transformadores de mónada son funciones de tipo que, cuando se aplican a un tipo de mónada, generan una nueva mónada, que combina el comportamiento de ambos componentes.
Por ejemplo, en el administrador de ventanas xmonad
, los cálculos se ejecutan dentro de:
newtype X a = X (ReaderT XConf (StateT XState IO) a)
es decir, un Reader
compuesto con un State
y una mónada IO
.
-
Reader
da acceso a la memoria de solo lectura -
State
proporciona una forma de estado de lectura y escritura -
IO
permite efectos externos arbitrarios
Tenga en cuenta que las transformaciones de mónada son, por lo tanto, tipos de rango superior. Toman un tipo de tipo monádico ( * -> *
) y producen un nuevo tipo de ese tipo.
Como siempre, la wiki de Haskell tiene algunos contenidos útiles:
Donde todo comenzo: