Quelle est une bonne façon de concevoir / structurer de grands programmes fonctionnels, en particulier dans Haskell?
J'ai parcouru un tas de tutoriels (Write Yourself a Scheme étant mon préféré, avec Real World Haskell juste après) - mais la plupart des programmes sont relativement petits et à usage unique. De plus, je ne considère pas que certains d'entre eux soient particulièrement élégants (par exemple, les vastes tables de recherche dans WYAS).
Je veux maintenant écrire des programmes plus grands, avec plus de pièces mobiles - acquérir des données à partir d'une variété de sources différentes, les nettoyer, les traiter de différentes manières, les afficher dans les interfaces utilisateur, les conserver, communiquer sur les réseaux, etc. une meilleure structure de ce code pour être lisible, maintenable et adaptable aux exigences changeantes?
Il existe une assez grande littérature traitant de ces questions pour les grands programmes impératifs orientés objet. Des idées comme MVC, des modèles de conception, etc. sont des prescriptions décentes pour atteindre des objectifs généraux tels que la séparation des préoccupations et la réutilisabilité dans un style OO. De plus, les nouveaux langages impératifs se prêtent à un style de refactoring de conception à mesure que vous grandissez auquel, à mon avis novice, Haskell semble moins bien adapté.
Existe-t-il une littérature équivalente pour Haskell? Comment le zoo des structures de contrôle exotiques disponibles en programmation fonctionnelle (monades, flèches, applicatives, etc.) est-il le mieux employé à cet effet? Quelles meilleures pratiques pourriez-vous recommander?
Merci!
EDIT (ceci fait suite à la réponse de Don Stewart):
@dons a mentionné: "Les monades capturent les conceptions architecturales clés en types."
Je suppose que ma question est: comment penser les conceptions architecturales clés dans un langage fonctionnel pur?
Prenons l'exemple de plusieurs flux de données et de plusieurs étapes de traitement. Je peux écrire des analyseurs modulaires pour les flux de données dans un ensemble de structures de données, et je peux implémenter chaque étape de traitement comme une fonction pure. Les étapes de traitement requises pour une donnée dépendront de sa valeur et des autres. Certaines étapes doivent être suivies d'effets secondaires tels que les mises à jour de l'interface graphique ou les requêtes de base de données.
Quelle est la «bonne» façon de lier les données et les étapes d'analyse d'une manière agréable? On pourrait écrire une grosse fonction qui fait ce qu'il faut pour les différents types de données. Ou on pourrait utiliser une monade pour garder une trace de ce qui a été traité jusqu'à présent et que chaque étape de traitement obtienne tout ce dont elle a besoin à partir de l'état de la monade. Ou on pourrait écrire des programmes largement séparés et envoyer des messages (je n'aime pas beaucoup cette option).
Les diapositives qu'il a liées ont une puce Things we Need: "Idioms for mapping design on types / functions / classes / monads". Quels sont les idiomes? :)