什么是设计/构造大型功能程序的好方法,尤其是在 Haskell 中?
我已经阅读了很多教程(Write Yourself a Scheme 是我最喜欢的,Real World Haskell 紧随其后)——但大多数程序都相对较小,而且用途单一。此外,我不认为其中一些特别优雅(例如,WYAS 中的大量查找表)。
我现在想编写更大的程序,有更多的移动部分——从各种不同的来源获取数据,清理它,以各种方式处理它,在用户界面中显示它,持久化它,通过网络通信等等。怎么可能一种最好的代码结构是清晰、可维护和适应不断变化的需求?
对于大型面向对象的命令式程序,有相当多的文献解决了这些问题。MVC、设计模式等想法是实现诸如关注点分离和面向对象风格中的可重用性等广泛目标的不错的处方。此外,较新的命令式语言适用于“随成长而设计”的重构风格,在我的新手看来,Haskell 似乎不太适合这种风格。
是否有与 Haskell 相当的文献?函数式编程(单子,箭头,应用程序等)中可用的奇异控制结构的动物园如何最好地用于此目的?您可以推荐哪些最佳实践?
谢谢!
编辑(这是唐斯图尔特回答的后续行动):
@dons 提到:“Monads 以类型捕获关键架构设计。”
我想我的问题是:一个人应该如何用一种纯函数式语言来思考关键的架构设计?
考虑几个数据流和几个处理步骤的例子。我可以将数据流的模块化解析器编写为一组数据结构,并且可以将每个处理步骤实现为纯函数。一条数据所需的处理步骤将取决于其价值和其他数据。某些步骤之后应该有一些副作用,例如 GUI 更新或数据库查询。
以一种很好的方式将数据和解析步骤联系起来的“正确”方法是什么?可以编写一个大函数来为各种数据类型做正确的事情。或者可以使用 monad 来跟踪到目前为止已处理的内容,并让每个处理步骤从 monad 状态中获取下一步需要的任何内容。或者可以编写大部分独立的程序并发送消息(我不太喜欢这个选项)。
他链接的幻灯片有一个“我们需要的东西”项目符号:“将设计映射到类型/函数/类/单子的惯用语”。有哪些成语?:)
我在 Haskell 的 Engineering Large Projects和 XMonad的设计和实现中谈到了这一点。大工程是关于管理复杂性的。Haskell 中用于管理复杂性的主要代码结构机制是:
类型系统
分析器
纯度
测试
用于结构化的单子
类型类和存在类型
并发和并行
par
重构
明智地使用 FFI
元编程
包装和分销
警告
-Wall
使用所有这些工具,您可以控制复杂性,尽可能多地消除组件之间的交互。理想情况下,你有一个非常大的纯代码库,这很容易维护,因为它是组合的。这并不总是可能的,但值得瞄准。
一般来说:将系统的逻辑单元 分解 成最小的引用透明组件,然后在模块中实现它们。组件集(或内部组件)的全局或本地环境可能会映射到 monad。使用代数数据类型来描述核心数据结构。广泛分享这些定义。