mtl, transformers, monads-fd, monadLib y la paradoja de la elección

92

Hackage tiene varios paquetes para transformadores de mónadas:

  • mtl : biblioteca de transformadores Monad
  • transformadores : functor de hormigón y transformadores de mónada
  • monads-fd : clases de mónadas , usando dependencias funcionales
  • monads-tf : clases de mónadas , utilizando familias de tipos
  • monadLib : una colección de transformadores de mónada.
  • mtl-tf : biblioteca de transformadores de mónadas que utiliza familias de tipos.
  • mmtl : biblioteca de transformadores Modular Monad
  • mtlx : biblioteca de transformadores Monad con índices de tipo, que proporciona copias 'gratuitas'
  • compose-trans : transformadores de mónada componibles

(y tal vez me perdí algunos)

¿Cuál usaremos?

mtl es el de la plataforma Haskell, pero sigo escuchando en reddit que no es genial.

Pero lo malo de la elección de todos modos, ¿no es solo algo bueno?

Bueno, vi cómo, por ejemplo, los autores de data-accessor tuvieron que hacer todo esto para atender solo las opciones populares:

  • biblioteca data-accessor-monadLib: funciones de acceso para las mónadas de monadLib
  • biblioteca data-accessor-monads-fd: use Accessor para acceder al estado en la clase monad State monads-fd
  • biblioteca data-accessor-monads-tf: Utilice Accessor para acceder al estado en la familia de tipos de mónadas de estado monads-tf
  • biblioteca data-accessor-mtl: use Accessor para acceder al estado en la clase mtl State monad
  • biblioteca data-accessor-transformers: use Accessor para acceder al estado en la mónada de estado de los transformadores

Me imagino que si esto continúa y, por ejemplo, evolucionan varios paquetes de Arrow de la competencia, podríamos ver algo como: Spoonklink-Arrow-Transformers, Spoonklink-Arrow-MonadLib, Spoonklink-tfArrows-Transformers, Spoonklink-tfArrows-monadLib, ...

Y luego me preocupa que si se bifurca Spoonklink, Hackage se quedará sin espacio en disco. :)

Preguntas:

  • ¿Por qué hay tantos paquetes de transformadores de mónadas?
  • ¿Por qué mtl [se considera] poco cool?
  • ¿Cuáles son las diferencias clave?
  • La mayoría de estos paquetes aparentemente competidores fueron escritos por Andy Gill y son mantenidos por Ross Paterson. ¿Significa esto que estos paquetes no compiten sino que funcionan juntos de alguna manera? ¿Y Andy y Ross consideran obsoleto alguno de sus propios paquetes?
  • ¿Cuál deberíamos usar tú y yo?
yairchu
fuente
2
Este enlace me ayudó a entender mtl vs transformers haskell.org/haskellwiki/Monad_Transformer_Library
Brandon Cook
2
¡Desplácese hacia abajo para ver el comentario de @jberryman ! Use mtl o transfomers, ¡se volvieron compatibles!
Sophie

Respuestas:

70

Algunos de ellos son casi completamente equivalentes:

  • mtlusa extensiones GHC, pero transformerses Haskell 98.
  • monads-fdy monads-tfson complementos de transformers, utilizando dependencias funcionales y familias de tipos, respectivamente, y ambos proporcionan la funcionalidad mtlque falta transformers.
  • mtl-tfse mtlvuelve a implementar utilizando familias tipográficas.

Entonces, esencialmente, mtl== transformers++ monads-fd, mtl-tf== transformers++ monads-tf. Creo que la portabilidad y modularidad mejoradas transformersy sus paquetes asociados es la razón por la que no mtlestá de moda en estos días.

mmtly mtlxambos parecen ser similares y / o basados ​​en mtl, con diferencias de API y características adicionales.

MonadLibparece tener una visión bastante diferente de las cosas, pero no estoy familiarizado con él directamente. También parece utilizar muchas extensiones GHC, más que las demás.

A simple vista, compose-transparece ser más una metaprogramación para crear transformadores de mónadas. Dice ser compatible con lo Control.Monad.Transque ... supongo que significa mtl.

En cualquier caso, sugiero el siguiente algoritmo de decisión:

  • ¿Necesitas mónadas estándar para un nuevo proyecto? Use transformers& co., Ayúdenos mtla descansar.
  • ¿Ya lo está utilizando mtlen un gran proyecto? transformersno es completamente compatible, pero nadie te matará por no cambiar.
  • ¿Alguno de los otros paquetes proporciona la funcionalidad inusual que necesita? También podría usarlo en lugar de enrollar el suyo.
  • ¿Aún no estás satisfecho? Tíralos a todos, descárgalos category-extrasy resuelve todos los problemas del mundo con una página y media de un código increíblemente genérico e incomprensible y abstracto .
CA McCann
fuente
2
si mtl == transformers ++ monads-fd, ¿no podría simplemente implementarse de esta manera? (como una fase para reemplazarlo) que eliminaría la necesidad de tener cosas como data-accessor-mtl
yairchu
2
@yairchu: Bueno, sí, pero ¿qué esperas que haga al respecto? :) Mantener la compatibilidad con versiones anteriores nunca es tan fácil como parece, y cambiar las bibliotecas clave requiere tiempo, esfuerzo y cierto grado de apoyo de la comunidad. La situación del transformador de mónada es un problema conocido, pero no creo que sea la máxima prioridad de nadie ni mucho menos.
CA McCann
5
@yairchu: eso es básicamente lo que se está haciendo. la próxima versión principal de mtl debería ser un stub que importe transformers + monads-fd, y la compatibilidad con esa versión será el factor decisivo. Luego, las bibliotecas podrán actualizarse individualmente para que sean compatibles con mtl 1.1 y 1.2, y luego las aplicaciones se encasillan en la versión que esté instalada o sea requerida por su dependencia de biblioteca más restrictiva.
Edward KMETT
2
La lista de correo de las bibliotecas está discutiendo la posibilidad de mover MonadIO (y posiblemente MonadTrans de mtl a la base. Aunque, se ha suspendido la posibilidad de extraer MonadIO o una MonadBase más general a pesar del hecho de que "MonadBase" necesita MPTC, fundeps, etc. .
Edward KMETT
27
Desde que encontré esta publicación extremadamente informativa. Pensé que actualizaría a otros googlers: mtl ahora depende de transformers, monads-fd ahora es un stub alrededor de mtl. Por lo tanto, use mtl si necesita los beneficios adicionales que tiene, o simplemente importe transformadores si tiene todo lo que necesita.
jberryman
20

¿Por el momento? Probablemente deberías usar mtl. Lo que ocurre es que la transformersbiblioteca se está factorizado fuera del MTL de una manera que monads-fdy monads-tfpueden coexistir en paz, pero en el cheque pasado que aún no era el caso.

Cuando eso suceda, podrá importar monads-fdy transformersobtener (casi) la misma interfaz, con la excepción de que State, etc. será un alias para StateT.

Así que escribiría a mtl, pero no confiaría en el hecho de que State, Reader, etc. son actualmente, dataya que serán reemplazados por types.

MonadLib es otra alternativa en la que ha estado trabajando Iavor, que se puede utilizar de forma segura porque no comparte ningún nombre de módulo con los demás, pero que tiene un patrón de uso bastante diferente.

Edward KMETT
fuente
4
¿Coexistir en qué sentido? ¿Usado por el mismo paquete? ¿Importado en el mismo módulo? ¿Combinados en la misma pila de transformadores? Mezclar fondos y TF me parece una mala idea, en general. De todos modos, no he hecho un uso extensivo de transformers& co. todavía, pero no noté ningún problema aparte de algunas diferencias menores de API frente mtlal cambio de código (bastante simple).
CA McCann
4
El problema se reduce al hecho de que solo puede cargar un paquete que proporcione un módulo determinado. Entonces, si usa una biblioteca que usa mtl, incluso internamente, no puede importar una alternativa. Actualmente, un buen porcentaje de piratería utiliza el mtl internamente de alguna manera. Varias personas prefieren usar familias de tipos, y monads-tf les da eso, pero tenga en cuenta que en este momento, hasta que se complete la refactorización de transformers + monads-fd, esto bloquea ese código para que no use cualquier biblioteca que requiera MTL de manera transitiva. . Eso incluye algunos artículos bastante caros.
Edward KMETT
1
El uso de transformadores + mónadas- (tf | fd) evitará a largo plazo ese problema, pero todavía no lo hemos logrado. Mientras tanto, la preponderancia del uso está a favor de mtl. La ruta de actualización parece ser que la próxima versión principal de mtl se redefinirá como un stub que importa monads-fd y transformers. La ruptura de la versión principal proporciona una buena manera de indicar en su archivo de cabal que no le importa qué versión obtenga (es decir, no le importa que State sea un alias de tipo o un tipo de datos) y una vez que se produce el aumento de la versión principal, entonces no es necesario que le importe si todas las bibliotecas que utiliza comparten los mismos sesgos.
Edward KMETT
1
Entonces, en última instancia, su experiencia hasta ahora es exactamente para lo que están diseñados los transformadores / mónadas- (tf | fd). Pero, lo que se descubrió después de que se escribieron fue que la comunidad es bastante mala para cambiar de biblioteca, cuando no hay una razón convincente para saltar y un montón de razones heredadas para quedarse. De ahí la necesidad de redefinir mtl y dejar clara la ruta de actualización.
Edward KMETT
¡Genial, gracias por la aclaración detallada! Obviamente, el código que cambié tenía pocas dependencias externas, en su mayoría enlaces FFI, creo. Tampoco me di cuenta de que los conflictos de nombres de módulos eran tan ... invasivos, ¿supongo? Eso hace que las cosas sean realmente incómodas. :(
CA McCann
16

El factoring que Edward Kmett menciona en su respuesta se completó a finales de 2010. Su resultado final fue monads-fd , construido sobre transformadores , convirtiéndose en la versión 2 de mtl . Como consecuencia de la ubicuidad de mtl , las mónadas-tf nunca se pusieron de moda . A principios de 2017, mtl y transformers son las únicas bibliotecas de transformadores de mónadas que tienen un uso generalizado.

duplode
fuente