您如何用Haskell或其他功能编程语言设计程序?


52

我在面向对象的编程语言(例如C#或ruby)方面有一些经验。我知道如何设计面向对象风格的程序,如何创建类和对象,以及如何定义它们之间的关系。我也知道一些设计模式。

人们如何编写功能程序?他们如何开始?有功能语言的设计模式吗?极限编程或敏捷开发等方法是否适用于功能语言?


Answers:


24

尽管许多概念同样适用于其他功能语言(例如Erlang,Lisp(s)和ML),但我主要是在记住Haskell的情况下写我的答案。有些甚至在某种程度上适用于Ruby,Python,Perl和Javascript。

人们如何编写功能程序?他们如何开始?

通过编写函数。在进行函数式编程时,您正在编写main,或者正在编写辅助函数。有时,您的主要目标可能是编写一个具有各种相关功能的数据类型。

函数式编程非常适合自顶向下和自底向上方法。Haskell强烈建议您使用高级语言编写程序,然后简单地定义高级设计的细节。参见minimum,例如:

minimum    :: (Ord a) => [a] -> a
minimum xs =  foldl1 min xs

在列表中查找最小元素的功能只是遍历列表而已,使用min函数将每个元素与“累加器”或当前最小值进行比较。

有功能语言的设计模式吗?

有两种东西可以等同于“设计模式”,即恕我直言,高阶函数monad。让我们谈谈前者。高阶函数是将其他函数作为输入或将函数作为输出的函数。任何功能性的语言一般大量使用mapfilter以及fold(折叠通常也称为“减少”):三个非常基本的高阶函数,它们以不同的方式将函数应用于列表。这些以漂亮的方式代替了用于循环的样板。将函数作为参数传递给编程带来了极大的好处。通过使用高阶函数,能够创建自己的函数以及能够利用功能强大的标准库(其中包含有用的功能),可以更轻松地完成许多“设计模式”。

Monad是“更可怕”的话题。但是他们并不是真的那么恐怖。我最喜欢的想到单子的方法是将它们视为将功能封装在气泡中并赋予该功能超能力(仅在气泡内部起作用)。我可以详细说明,但是这个世界真的不需要再一个单子论证了。因此,我将举一些简单的例子。假设我要使用不确定的“设计模式”。我想同时为各种不同的输入运行相同的计算。我不想只选择一个输入,而是想全部选择。那就是清单monad:

allPlus2 :: [Int] -> [Int]
allPlus2 xs = do x <- xs
                 return (x + 2)

现在,执行此操作的惯用方法实际上是map,但出于说明的目的,您是否可以看到list monad如何让我编写一个函数,该函数看起来像在一个值上操作,但赋予了它对所有元素进行处理的超能力。一个列表?其他超级大国包括失败,状态,与“外部世界”交互以及并行执行。这些超能力非常强大,并且大多数编程语言都允许具有超能力的功能不断扩展。大多数人说Haskell根本不允许这些超级大国,但实际上,Haskell只是将它们包含在monad中,因此可以限制和观察它们的作用。

tl; dr Grokking高阶函数和monad是Haskell的等同于grokking设计模式。学习了这些Haskell概念之后,您就开始认为“设计模式”通常是廉价的变通办法,可以模拟Haskell的功能。

极限编程或敏捷开发等方法是否适用于功能语言?

我看不到任何将这些管理策略与任何一种编程范例联系在一起的东西。正如phynfo所说,函数式编程实际上迫使您进行函数分解,将一个大问题分解为子问题,因此微型里程碑应该是小菜一碟。有诸如QuickCheck和Zeno之类的工具可以测试甚至证明所编写函数的属性。


“我可以详细说明,但是这个世界真的并不需要另一个莫纳德的比喻。” -我们总是需要更多关于monad的类比,而您的类比是我见过的最好的类比之一。
亚当·根特

1
很好的答案,但是我认为您对设计模式的讨论有些误导。虽然您在Haskell中不需要OO / GOF风格的设计模式-实际上,尝试它们是很荒谬的-模式本身只是社区交流解决问题的方法。Haskell社区还很年轻,因此没有太多可谈论的模式,但是如果您问我有关Haskell模式的示例,我会提到GADT或Arrowized FRP之类的东西。
rtperson 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.