mtl, transformers, monads-fd, monadLib e il paradosso della scelta


92

Hackage ha diversi pacchetti per trasformatori monade:

  • mtl : libreria di trasformatori Monad
  • trasformatori : funtore concreto e trasformatori monade
  • monads-fd : classi Monad, che utilizzano dipendenze funzionali
  • monads-tf : classi Monad, utilizzando famiglie di tipi
  • monadLib : una raccolta di trasformatori monade.
  • mtl-tf : libreria di trasformatori Monad che utilizza famiglie di tipi.
  • mmtl : libreria di trasformatori modulari Monad
  • mtlx : libreria di trasformatori Monad con indici di tipo, che fornisce copie "gratuite".
  • compose-trans : trasformatori monade componibili

(e forse me ne sono perso qualcuno)

Quale dovremmo usare?

mtl è quello nella piattaforma Haskell, ma continuo a sentire su reddit che non è cool.

Ma cosa c'è di male nella scelta comunque, non è solo una cosa buona?

Bene, ho visto come ad esempio gli autori di data-accessor hanno dovuto fare tutto questo per soddisfare solo le scelte popolari:

  • libreria data-accessor-monadLib: funzioni accessor per le monadi monadLib
  • libreria data-accessor-monads-fd: usa Accessor per accedere allo stato nella classe monads-fd State monad
  • libreria data-accessor-monads-tf: utilizzare Accessor per accedere allo stato nella famiglia di tipi monade monads-tf State
  • libreria data-accessor-mtl: usa Accessor per accedere allo stato nella classe monade mtl State
  • libreria data-accessor-transformers: usa Accessor per accedere allo stato in transformers State monad

Immagino che se questo va avanti e ad esempio si evolvono diversi pacchetti Arrow concorrenti, potremmo vedere qualcosa come: spoonklink-frecce-transformers, spoonklink-frecce-monadLib, spoonklink-tfArrows-transformers, spoonklink-tfArrows-monadLib, ...

E poi mi preoccupo che se Spoonklink viene biforcato, Hackage esaurirà lo spazio su disco. :)

Domande:

  • Perché ci sono così tanti pacchetti di trasformatori monade?
  • Perché mtl [considerato] uncool?
  • Quali sono le principali differenze?
  • La maggior parte di questi pacchetti apparentemente concorrenti sono stati scritti da Andy Gill e sono mantenuti da Ross Paterson. Questo significa che questi pacchetti non sono in competizione ma piuttosto lavorano insieme in qualche modo? E Andy e Ross considerano obsoleto qualcuno dei loro pacchetti?
  • Quale dovremmo usare io e te?

2
Questo collegamento mi ha aiutato a capire mtl vs transformers haskell.org/haskellwiki/Monad_Transformer_Library
Brandon Cook

2
Scorri verso il basso per il commento di @jberryman ! Usa mtl o transfomers, sono diventati compatibili!
Sophie

Risposte:


70

Alcuni di loro sono quasi completamente equivalenti:

  • mtlutilizza estensioni GHC, ma transformersè Haskell 98.
  • monads-fde monads-tfsono componenti aggiuntivi di transformers, utilizzando rispettivamente dipendenze funzionali e famiglie di tipi, che forniscono entrambe le funzionalità mtlche mancano transformers.
  • mtl-tfviene mtlreimplementato utilizzando famiglie di tipi.

Quindi essenzialmente, mtl== transformers++ monads-fd, mtl-tf== transformers++ monads-tf. La migliore portabilità e modularità di transformerse dei suoi pacchetti associati è il motivo per cui non mtlè cool in questi giorni, penso.

mmtled mtlxentrambi sembrano essere simili e / o basati su mtl, con differenze API e funzionalità extra.

MonadLibsembra avere una visione piuttosto diversa delle cose, ma non ne ho familiarità direttamente. Inoltre sembra utilizzare molte estensioni GHC, più delle altre.

A prima vista compose-transsembra più simile alla metaprogrammazione per creare trasformatori monade. Sostiene di essere compatibile con Control.Monad.Transquale ... immagino significhi mtl?

In ogni caso, suggerirei il seguente algoritmo decisionale:

  • Hai bisogno di monadi standard per un nuovo progetto? Usa transformers& co., Aiutaci mtla riposare.
  • Stai già utilizzando mtlin un grande progetto? transformersnon è completamente compatibile, ma nessuno ti ucciderà per non aver cambiato.
  • Uno degli altri pacchetti fornisce funzionalità insolite di cui hai bisogno? Tanto vale usarlo piuttosto che rotolare il tuo.
  • Ancora insoddisfatto? Buttali tutti fuori, scarica category-extrase risolvi tutti i problemi del mondo con una pagina e mezza di incomprensibili sciocchezze astratte di codice incredibilmente generico.

2
se mtl == transformers ++ monads-fd, non potrebbe essere implementato in questo modo? (come fase verso la sua sostituzione) che
eliminerebbe

2
@yairchu: Ebbene sì, ma cosa ti aspetti che io faccia al riguardo? :) Mantenere la retrocompatibilità non è mai così facile come sembra e la modifica delle librerie chiave richiede tempo, impegno e un certo grado di supporto da parte della comunità. La situazione del trasformatore della monade è un problema noto ma non credo che sia la massima priorità di nessuno di gran lunga.
CA McCann

5
@yairchu: questo è fondamentalmente ciò che viene fatto. la prossima versione principale di mtl dovrebbe essere uno stub che importa trasformatori + monadi-fd, e la compatibilità con quella versione sarà il fattore decisivo. Le librerie potranno quindi essere aggiornate individualmente in modo che siano compatibili sia con mtl 1.1 che con 1.2, quindi le app verranno classificate in qualsiasi versione sia installata o richiesta dalla loro dipendenza dalla libreria più restrittiva.
Edward KMETT

2
La mailing list delle biblioteche sta attualmente discutendo di spostare MonadIO (e forse MonadTrans da mtl a base. Anche se è stato sospeso se estrarre MonadIO o un MonadBase più generale nonostante il fatto che "MonadBase" abbia bisogno di MPTC, fundeps, ecc. .
Edward KMETT

27
Da quando ho trovato questo post estremamente informativo. Ho pensato di aggiornare altri googler: mtl ora dipende dai trasformatori, monads-fd è ora uno stub attorno a mtl. Quindi usa mtl se hai bisogno delle chicche extra che ha, o importa semplicemente trasformatori se ha tutto ciò di cui hai bisogno.
jberryman

20

Per il momento? Probabilmente dovresti usare mtl. Quello che sta accadendo è che la transformerslibreria viene scomposto fuori del MTL in un modo che monads-fde monads-tfpossono coesistere pacificamente, ma in ultimo controllo che non era ancora il caso.

Quando ciò accade, sarai in grado di importare monads-fde transformersottenere (quasi) la stessa interfaccia, con l'eccezione che State, ecc. Sarà un alias per StateT.

Quindi scriverei a mtl, ma non mi baserei sul fatto che State, Reader, ecc. Sono attualmente datain quanto verranno sostituiti con types.

MonadLib è un'altra alternativa su cui ha lavorato Iavor, che può essere tranquillamente utilizzata perché non condivide alcun nome di modulo con gli altri, ma che ha un modello di utilizzo abbastanza diverso.


4
Co-esistere in che senso? Utilizzato dallo stesso pacchetto? Importato nello stesso modulo? Combinato nello stesso stack del trasformatore? Mescolare fondi e TF mi sembra una cattiva idea, in generale. Comunque, non ho fatto un ampio uso di transformers& co. ma non ha notato alcun problema oltre ad alcune piccole differenze API rispetto mtlal cambio di codice (abbastanza semplice).
CA McCann

4
Il problema dipende dal fatto che puoi caricare solo un pacchetto che fornisce un dato modulo. Quindi se usi una libreria che usa mtl, anche internamente, non puoi importare un'alternativa. Attualmente una buona percentuale di hackage utilizza in qualche modo internamente mtl. Un certo numero di persone preferisce usare famiglie di tipi e monads-tf glielo dà, ma tieni presente che al momento, fino al completamento del refactoring di transformers + monads-fd questo blocca quel codice dall'utilizzo di qualsiasi libreria che richiede MTL in modo transitorio . Ciò include alcuni elementi del biglietto piuttosto grandi.
Edward KMETT

1
L'uso di trasformatori + monadi- (tf | fd) eviterà a lungo termine quel sottaceto, ma non siamo ancora arrivati. Nel frattempo la preponderanza di utilizzo è a favore di mtl. Il percorso di aggiornamento sembra essere che la prossima versione principale di mtl sarà ridefinita come uno stub che importa monadi-fd e trasformatori. L'interruzione della versione principale fornisce un buon modo per affermare nel tuo file cabal che non ti interessa quale versione ottieni (cioè non ti interessa che lo stato sia un alias di tipo o un tipo di dati) e una volta che si verifica l'urto della versione principale, allora non devi preoccuparti se tutte le librerie che usi condividono gli stessi pregiudizi.
Edward KMETT

1
Quindi, in ultima analisi, la tua esperienza fino ad ora è esattamente ciò che transformers / monads- (tf | fd) sono progettati per supportare. Ma quello che è stato realizzato dopo che sono stati scritti è che la comunità è piuttosto pessima nel cambiare biblioteche, quando non c'è una ragione convincente per saltare e un sacco di motivi legacy per restare. Da qui la necessità di ridefinire mtl e rendere chiaro il percorso di upgrade.
Edward KMETT

Fantastico, grazie per il chiarimento dettagliato! Ovviamente, il codice che ho cambiato aveva poche dipendenze esterne, per lo più collegamenti FFI, credo. Inoltre non mi rendevo conto che i conflitti tra i nomi dei moduli fossero così ... invasivi, immagino? Questo rende le cose davvero imbarazzanti. :(
CA McCann

16

Il factoring di Edward Kmett menzionato nella sua risposta è stato completato alla fine del 2010. Il suo risultato finale è stato monads-fd , costruito su trasformatori , che è diventato la versione 2 di mtl . Come conseguenza dell'ubiquità di mtl , le monadi-tf non hanno mai preso piede . Dall'inizio del 2017, mtl e transformers sono le uniche librerie di trasformatori monad che vedono un utilizzo diffuso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.