Qual é uma boa maneira de projetar / estruturar grandes programas funcionais, especialmente em Haskell?
Passei por vários tutoriais (Escreva para si mesmo um esquema, sendo o meu favorito, com o Real World Haskell por um segundo) - mas a maioria dos programas é relativamente pequena e tem um único objetivo. Além disso, não considero alguns deles particularmente elegantes (por exemplo, as vastas tabelas de pesquisa no WYAS).
Agora estou querendo escrever programas maiores, com mais partes móveis - adquirindo dados de várias fontes diferentes, limpando-os, processando-os de várias maneiras, exibindo-os em interfaces de usuário, persistindo-os, comunicando-se através de redes, etc. Qual a melhor estrutura para que esse código seja legível, sustentável e adaptável às mudanças de requisitos?
Existe uma literatura bastante ampla abordando essas questões para grandes programas imperativos orientados a objetos. Idéias como MVC, padrões de design etc. são prescrições decentes para a realização de objetivos amplos, como separação de preocupações e reutilização no estilo OO. Além disso, as novas linguagens imperativas se prestam a um estilo de refatoração de 'design à medida que você cresce', para o qual, na minha opinião de principiante, Haskell parece menos adequado.
Existe uma literatura equivalente para Haskell? Como o zoológico de estruturas de controle exóticas está disponível na programação funcional (mônadas, flechas, aplicativos etc.) melhor empregado para esse fim? Quais práticas recomendadas você recomendaria?
Obrigado!
EDIT (este é um seguimento da resposta de Don Stewart):
@dons mencionados: "Mônadas capturam os principais projetos arquitetônicos em tipos".
Acho que minha pergunta é: como pensar sobre os principais projetos arquitetônicos em uma linguagem funcional pura?
Considere o exemplo de vários fluxos de dados e várias etapas de processamento. Posso escrever analisadores modulares para os fluxos de dados em um conjunto de estruturas de dados e implementar cada etapa do processamento como uma função pura. As etapas de processamento necessárias para um dado dependerão de seu valor e de outros. Algumas das etapas devem ser seguidas por efeitos colaterais, como atualizações da GUI ou consultas ao banco de dados.
Qual é a maneira 'correta' de vincular os dados e as etapas de análise de uma maneira agradável? Pode-se escrever uma grande função que faz a coisa certa para os vários tipos de dados. Ou pode-se usar uma mônada para acompanhar o que foi processado até agora e cada etapa do processamento obter o que for necessário do estado de mônada. Ou pode-se escrever programas em grande parte separados e enviar mensagens (não gosto muito dessa opção).
Os slides que ele vinculou têm um marcador Coisas que precisamos: "Expressões idiomáticas para mapear o design em tipos / funções / classes / mônadas". Quais são os idiomas? :)