mtl, transformers, monads-fd, monadLib i paradoks wyboru

91

Hackage ma kilka pakietów dla transformatorów monad:

  • mtl : Biblioteka transformatorów Monad
  • transformatory : funktor do betonu i transformatory monadowe
  • monads-fd : Klasy Monad, używające zależności funkcjonalnych
  • monads-tf : Klasy Monad, używające rodzin typów
  • monadLib : kolekcja transformatorów monad.
  • mtl-tf : biblioteka transformatorów Monad korzystająca z rodzin typów.
  • mmtl : Modularna biblioteka transformatorów Monad
  • mtlx : Biblioteka transformatora Monad z indeksami typów, zapewniająca „darmowe” kopie.
  • compose-trans : Komponowalne transformatory monadowe

(a może trochę przegapiłem)

Którego użyjemy?

mtl jest tym na platformie Haskell, ale ciągle słyszę na reddicie, że jest niefajny.

Ale co jest złego w wyborze, czy nie jest to po prostu dobra rzecz?

Cóż, widziałem, jak na przykład autorzy akcesorów danych musieli zrobić to wszystko, aby zaspokoić tylko popularne wybory:

  • biblioteka danych-accessor-monadLib: Funkcje pomocnicze dla monad monadLib
  • data-accessor-monads-fd library: Użyj Accessor, aby uzyskać dostęp do stanu w klasie monads-fd State monad
  • data-accessor-monads-tf library: Użyj Accessor, aby uzyskać dostęp do stanu w rodzinie typów monad-tf State monad
  • data-accessor-mtl biblioteka: Użyj Accessor, aby uzyskać dostęp do stanu w klasie monad stanu mtl
  • biblioteka transformersów dostępu do danych: Użyj Accessor, aby uzyskać dostęp do stanu w monadzie stanu transformatorów

Wyobrażam sobie, że jeśli tak się stanie i na przykład kilka konkurencyjnych pakietów Arrow ewoluuje, możemy zobaczyć coś takiego: spoonklink-arrows-transformers, spoonklink-arrows-monadLib, spoonklink-tfArrows-transformers, spoonklink-tfArrows-monadLib, ...

A potem martwię się, że jeśli Spoonklink zostanie rozwidlony, Hackage zabraknie miejsca na dysku. :)

Pytania:

  • Dlaczego jest tak wiele pakietów transformatorów Monad?
  • Dlaczego mtl [uważa się] za niefajne?
  • Jakie są kluczowe różnice?
  • Większość z tych pozornie konkurujących ze sobą pakietów została napisana przez Andy'ego Gilla i jest zarządzana przez Rossa Patersona. Czy to oznacza, że ​​te pakiety nie konkurują ze sobą, ale w jakiś sposób ze sobą współpracują? I czy Andy i Ross uważają któryś z ich własnych pakietów za przestarzały?
  • Którego powinieneś użyć?
yairchu
źródło
2
Ten link pomógł mi zrozumieć mtl vs transformers haskell.org/haskellwiki/Monad_Transformer_Library
Brandon Cook
2
Przewiń w dół, aby zobaczyć komentarz @jberryman ! Użyj mtl lub transfomerów, stały się kompatybilne!
Sophie

Odpowiedzi:

70

Kilka z nich jest prawie całkowicie równoważnych:

  • mtlużywa rozszerzeń GHC, ale transformersjest Haskell 98.
  • monads-fdi monads-tfsą dodatkami transformers, używającymi odpowiednio zależności funkcjonalnych i rodzin typów, zapewniających funkcjonalność, mtlktórej brakuje transformers.
  • mtl-tfjest mtlponownie zaimplementowany przy użyciu rodzin typów.

Więc zasadniczo mtl== transformers++ monads-fd, mtl-tf== transformers++ monads-tf. Wydaje mi się, że ulepszona przenośność i modułowość transformerspakietów oraz powiązanych z nimi pakietów jest mtlobecnie niefajna.

mmtli mtlxoba wydają się być podobne i / lub oparte na mtlróżnicach API i dodatkowych funkcjach.

MonadLibwydaje się mieć nieco inne podejście do spraw, ale nie znam tego bezpośrednio. Wydaje się również, że używa wielu rozszerzeń GHC, więcej niż inne.

Na pierwszy rzut oka compose-transwydaje się, że bardziej przypomina metaprogramowanie do tworzenia transformatorów monadowych. Twierdzi, że jest kompatybilny z Control.Monad.Transktórym ... chyba oznacza mtl?

W każdym razie sugerowałbym następujący algorytm decyzyjny:

  • Potrzebujesz standardowych monad do nowego projektu? Użyj transformers& co., Pomóż nam mtlodpocząć.
  • Czy używasz już mtlw dużym projekcie? transformersnie jest w pełni kompatybilny, ale nikt cię nie zabije za brak przełączenia.
  • Czy któryś z pozostałych pakietów zapewnia niezwykłą funkcjonalność, której potrzebujesz? Równie dobrze możesz go użyć, zamiast skręcać własną.
  • Wciąż nie jesteś zadowolony? Wyrzuć je wszystkie, pobierz category-extrasi rozwiąż wszystkie problemy świata za pomocą półtorej strony niezrozumiałego abstrakcyjnego nonsensu, zapierającego dech w piersiach kodu ogólnego.
CA McCann
źródło
2
jeśli mtl == transformers ++ monads-fd, czy nie można tego po prostu zaimplementować w ten sposób? (jako faza w kierunku jego zastąpienia), które wyeliminowałyby potrzebę posiadania rzeczy takich jak data-accessor-mtl
yairchu
2
@yairchu: No tak, ale czego oczekujesz ode mnie? :) Utrzymanie wstecznej kompatybilności nigdy nie jest tak łatwe, jak się wydaje, a zmiana kluczowych bibliotek wymaga czasu, wysiłku i pewnego stopnia wsparcia społeczności. Sytuacja z transformatorem monadowym jest znanym problemem, ale nie sądzę, aby była to dla kogokolwiek priorytet z dalszej perspektywy.
CA McCann
5
@yairchu: w zasadzie tak właśnie się dzieje. następna główna wersja mtl powinna być odgałęzieniem importującym transformers + monads-fd, a zgodność z tą wersją będzie decydującym czynnikiem. Biblioteki będą wtedy mogły być indywidualnie aktualizowane, aby były zgodne zarówno z mtl 1.1, jak i 1.2, a następnie aplikacje zostaną zaszufladkowane do dowolnej wersji, która jest zainstalowana lub jest wymagana przez ich najbardziej restrykcyjną zależność od biblioteki.
Edward KMETT
2
Lista mailingowa bibliotek aktualnie dyskutuje o przeniesieniu MonadIO (i być może MonadTrans z mtl do bazy. Mimo, że zostało zawieszone, czy wyodrębnić MonadIO, czy bardziej ogólną MonadBase, pomimo faktu, że "MonadBase" potrzebuje MPTC, funduszy itp. .
Edward KMETT
28
Ponieważ uznałem ten post za niezwykle pouczający. Pomyślałem, że zaktualizuję innych pracowników Google: mtl zależy teraz od transformatorów, monads-fd jest teraz odgałęzieniem wokół mtl. Więc użyj mtl, jeśli potrzebujesz dodatkowych gadżetów, które ma, lub po prostu importuj transformatory, jeśli ma wszystko, czego potrzebujesz.
jberryman
19

Na chwilę? Powinieneś prawdopodobnie użyć mtl. Dzieje się tak, że transformersbiblioteka jest wyodrębniana z MTL w sposób, który monads-fdi monads-tfmoże współistnieć pokojowo, ale w końcu to jeszcze nie było.

Kiedy tak się stanie, będziesz mógł zaimportować monads-fdi transformersuzyskać (prawie) ten sam interfejs, z wyjątkiem tego State, że itp. Będzie aliasem dla StateT.

Piszę więc mtl, ale nie będę polegał na tym, że State, Reader itp. Są obecnie datatak, jak zostaną zastąpione przez types.

MonadLib to kolejna alternatywa, nad którą pracował Iavor, z której można bezpiecznie korzystać, ponieważ nie ma wspólnych nazw modułów z innymi, ale ma dość inny wzorzec użycia.

Edward KMETT
źródło
4
W jakim sensie współistnieją? Używany przez ten sam pakiet? Zaimportowano do tego samego modułu? Połączone w ten sam stos transformatorów? Generalnie mieszanie funduszy i TF wydaje mi się złym pomysłem. W każdym razie nie korzystałem zbytnio z transformers& co. jeszcze, ale nie zauważyłem żadnych problemów innych niż drobne różnice w API w porównaniu z mtlprzełączaniem jakiegoś (dość prostego) kodu.
CA McCann
4
Problem sprowadza się do tego, że można załadować tylko jeden pakiet, który udostępnia dany moduł. Więc jeśli używasz biblioteki, która używa mtl, nawet wewnętrznie, nie możesz zaimportować alternatywy. Obecnie znaczny procent hakerów w jakiś sposób wykorzystuje wewnętrznie MTL. Wielu ludzi woli używać rodzin typów, a monads-tf im to daje, ale należy pamiętać, że w tej chwili, dopóki transformers + monads-fd refaktoryzacja nie zostanie zakończona, blokuje to kodowanie przed użyciem jakichkolwiek bibliotek, które przejściowo wymagają MTL . Obejmuje to całkiem duże bilety.
Edward KMETT
1
Używanie transformatorów + monad- (tf | fd) pozwoli na dłuższą metę uniknąć tego zalewu, ale jeszcze tego nie zrobiliśmy. W międzyczasie większość użycia przemawia na korzyść mtl. Ścieżka aktualizacji wygląda na to, że następna główna wersja mtl zostanie przedefiniowana jako odgałęzienie importujące monads-fd i transformers. Główna przerwa w wersji zapewnia dobry sposób na stwierdzenie w pliku cabal, że nie obchodzi cię, którą wersję otrzymasz (tj. Nie obchodzi cię, czy Stan jest aliasem typu lub typem danych) i kiedy nastąpi zmiana wersji głównej nie musisz się przejmować, czy wszystkie biblioteki, z których korzystasz, mają takie same uprzedzenia.
Edward KMETT
1
Tak więc ostatecznie twoje dotychczasowe doświadczenia są dokładnie tym, do czego są zaprojektowane transformatory / monady- (tf | fd). Ale po ich napisaniu zdano sobie sprawę, że społeczność jest dość kiepska w zmienianiu bibliotek, podczas gdy nie ma ważnego powodu, aby skakać i mnóstwo tradycyjnych powodów, aby zostać. Stąd potrzeba przedefiniowania mtl i wyjaśnienia ścieżki aktualizacji.
Edward KMETT
Świetnie, dziękuję za szczegółowe wyjaśnienie! Oczywiście kod, który zmieniłem, miał kilka zewnętrznych zależności - myślę, że głównie powiązania FFI. Nie zdawałem sobie również sprawy, że konflikty nazw modułów były tak ... inwazyjne, jak sądzę? To rzeczywiście czyni rzeczy niezręcznymi. :(
CA McCann
16

Rozliczenie, o którym wspomina Edward Kmett w swojej odpowiedzi, zostało zakończone pod koniec 2010 roku. Efektem końcowym były monady-fd , zbudowane na transformatorach , stające się wersją 2 mtl . W konsekwencji wszechobecności MTL , monady-tf nigdy się nie przyjęły. Od początku 2017 r. Mtl i transformers są jedynymi bibliotekami transformatorów monad, które są szeroko stosowane.

duplode
źródło