Je suis novice en Haskell mais je comprends comment les transformateurs de monades peuvent être utilisés. Pourtant, j'ai toujours des difficultés à saisir l'avantage qu'ils prétendent avoir sur le passage de paramètres aux appels de fonctions.
Basé sur le wiki Les transformateurs de monades expliqués nous avons essentiellement un objet de configuration défini comme suit
data Config = Config Foo Bar Baz
et de le faire circuler, au lieu d'écrire des fonctions avec cette signature
client_func :: Config -> IO ()
nous utilisons un Transformateur de Monade de ReaderT et changeons la signature en
client_func :: ReaderT Config IO ()
tirer la Config est alors juste un appel à ask
.
L'appel de la fonction passe de client_func c
à runReaderT client_func c
Bien.
Mais pourquoi cela rend-il mon application plus simple ?
1- Je soupçonne que les transformateurs de monades ont un intérêt lorsque vous assemblez un grand nombre de fonctions/modules pour former une application. Mais c'est là que s'arrête ma compréhension. Quelqu'un pourrait-il m'éclairer ?
2- Je n'ai pas trouvé de documentation sur la façon d'écrire une grande modulaire en Haskell, où les modules exposent une certaine forme d'API et cachent leurs implémentations, tout en cachant (partiellement) leurs propres états et environnements aux autres modules. Des pistes, s'il vous plaît ?
(Edit : Real World Haskell déclare que "... cette approche [Monad Transformers] ... s'adapte à de plus gros programmes", mais il n'y a pas d'exemple clair démontrant cette affirmation).
EDIT suivant Chris Taylor Réponse ci-dessous
Chris explique parfaitement pourquoi l'encapsulation de Config, State, etc... dans un Transformer Monad apporte deux avantages :
- Elle évite qu'une fonction de niveau supérieur doive maintenir dans sa signature de type tous les paramètres requis par les (sous-)fonctions qu'elle appelle mais qui ne sont pas nécessaires pour sa propre utilisation (voir la section
getUserInput
fonction) - et, par conséquent, rend les fonctions de niveau supérieur plus résistantes à un changement du contenu de la monade transformateur (disons que vous voulez ajouter une fonction
Writer
pour fournir une journalisation dans une fonction de niveau inférieur)
Cela a pour conséquence de modifier la signature de toutes les fonctions afin qu'elles s'exécutent "dans" la monade transformatrice.
La question 1 est donc entièrement couverte. Merci Chris.
La réponse à la question 2 se trouve maintenant dans ce poste SO