Los candidatos componen, las mónadas no.
¿Qué significa la declaración anterior? ¿Y cuándo es preferible uno a otro?
haskell
functional-programming
monads
monad-transformers
applicative
desaparecido faktor
fuente
fuente

Applicatives son en realidad una familia completa deMonads, es decir, uno para cada "forma" de estructura posible.ZipListno es aMonad, peroZipLists de longitud fija son.Readeres un caso especial conveniente (¿o es general?) donde el tamaño de la "estructura" se fija como la cardinalidad del tipo de entorno.Readermónada hasta un isomorfismo. Una vez que fija la forma de un contenedor, codifica efectivamente una función a partir de posiciones, como un memo trie. Peter Hancock llama a estos functores "naperianos", ya que obedecen las leyes de los logaritmos.Respuestas:
Si comparamos los tipos
tenemos una pista de lo que separa los dos conceptos. Que
(s -> m t)en el tipo de(>>=)muestra que un valor enspuede determinar el comportamiento de un cálculo enm t. Las mónadas permiten la interferencia entre las capas de valor y de cálculo. El(<*>)operador no permite tal interferencia: los cálculos de la función y el argumento no dependen de los valores. Esto realmente muerde. Compararque utiliza el resultado de algún efecto para decidir entre dos cálculos (por ejemplo, lanzar misiles y firmar un armisticio), mientras que
que utiliza el valor de
abpara elegir entre los valores de dos cálculosatyaf, habiendo realizado ambos, quizás con efecto trágico.La versión monádica se basa esencialmente en el poder adicional de
(>>=)elegir un cálculo a partir de un valor, y eso puede ser importante. Sin embargo, apoyar ese poder hace que las mónadas sean difíciles de componer. Si intentamos construir 'doble vínculo'llegamos hasta aquí, pero ahora nuestras capas están revueltas. Tenemos un
n (m (n t)), así que tenemos que deshacernos del exteriorn. Como dice Alexandre C, podemos hacer eso si tenemos unpermutar el
ninterior yjoinel otron.La 'doble aplicación' más débil es mucho más fácil de definir
porque no hay interferencia entre las capas.
En consecuencia, es bueno reconocer cuándo realmente necesita la potencia adicional de
Monads, y cuándo puede salirse con la suya con la rígida estructura de cálculo queApplicativeadmite.Tenga en cuenta, por cierto, que aunque componer mónadas es difícil, puede ser más de lo que necesita. El tipo
m (n v)indica computación conm-effects, luego computación conn-effects a unv-valor, donde losm-effects terminan antes de quencomiencen los -effects (de ahí la necesidad deswap). Si solo desea intercalarm-efectos conn-efectos, entonces la composición es quizás demasiado pedir.fuente
mynsiempre se puede escribir un transformador mónadamt, y operar enn (m t)el usomt n t? Entonces, ¿siempre puedes componer mónadas, es más complicado, usar transformadores?data Free f x = Ret x | Do (f (Free f x)), entoncesdata (:+:) f g x = Inl (f x) | Tnr (g x), y considereFree (m :+: n). Eso retrasa la elección de cómo ejecutar intercalados.Maybeesto significa que un tempranoNothingsuprimirá la evaluaciónade un posterior / posteriorJust a. ¿Es esto correcto?Mónadas hacen componer, pero el resultado podría no ser una mónada. Por el contrario, la composición de dos aplicativos es necesariamente un aplicativo. Sospecho que la intención de la declaración original era que "la aplicabilidad compone, mientras que la mónada no". Reformulado, "
Applicativeestá cerrado bajo composición yMonadno lo es".fuente
Si tiene aplicativos
A1yA2, entonces el tipodata A3 a = A3 (A1 (A2 a))también es aplicativo (puede escribir tal instancia de forma genérica).Por otro lado, si usted tiene mónadas
M1yM2entonces el tipodata M3 a = M3 (M1 (M2 a))no es necesariamente una mónada (no hay una implementación genérica sensato>>=ojoinde la composición).Un ejemplo puede ser el tipo
[Int -> a](aquí componimos un constructor de tipos[]con(->) Int, los cuales son mónadas). Puedes escribir fácilmenteY eso se generaliza a cualquier aplicativo:
Pero no existe una definición sensata de
Si no está convencido de esto, considere esta expresión:
La longitud de la lista devuelta se debe establecer en piedra antes de que se proporcione un número entero, pero la longitud correcta depende del número entero que se proporcione. Por tanto, no
joinpuede existir una función correcta para este tipo.fuente
IOsin unMonadsería muy difícil de programar. :)Composición de mónadas, http://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf
fuente
swap : N M a -> M N aContT r m ano es nim (Cont r a)tampocoCont r (m a), yStateT s m aes más o menosReader s (m (Writer s a)).swapimplica que la composición permite a los dos "cooperar" de alguna manera. Además, tenga en cuenta quesequencees un caso especial de "intercambio" para algunas mónadas. Enfliprealidad, también lo es.swap :: N (M x) -> M (N x), me parece que puede usarreturns(adecuadamentefmapped) para insertar unMen el frente y unNen la parte posterior, yendo desdeN (M x) -> M (N (M (N x))), luego use eljoindel compuesto para obtener suM (N x).La solución de la ley distributiva l: MN -> NM es suficiente
para garantizar la monadicidad de NM. Para ver esto necesitas una unidad y un mult. Me enfocaré en el mult (la unidad es unit_N unitM)
Esto no garantiza que MN sea una mónada.
Sin embargo, la observación crucial entra en juego cuando tiene soluciones de ley distributiva
por tanto, LM, LN y MN son mónadas. Surge la pregunta de si LMN es una mónada (ya sea por
(MN) L -> L (MN) o por N (LM) -> (LM) N
Tenemos suficiente estructura para hacer estos mapas. Sin embargo, como observa Eugenia Cheng , necesitamos una condición hexagonal (que equivale a una presentación de la ecuación de Yang-Baxter) para garantizar la monadicidad de cualquier construcción. De hecho, con la condición hexagonal, las dos mónadas diferentes coinciden.
fuente