纯函数式编程

Posted

技术标签:

【中文标题】纯函数式编程【英文标题】:Purely Functional Programming 【发布时间】:2016-11-28 18:46:51 【问题描述】:

所以,我是一位经验丰富的 OOP 程序员(主要是 C++),现在刚刚开始涉足函数式编程。据我了解,在纯函数范式中,函数不应该有条件,应该尽可能使用柯里化来分解。有人可以为我提供以下示例的“纯”功能版本吗?最好使用将成为功能范式一部分的所有严格技术:

let rec greatestCommonFactor a b =
    if a = 0 then b
    elif a < b then greatestCommonFactor a (b - a)
    else greatestCommonFactor (a - b) b

【问题讨论】:

欢迎来到 Stack Overflow!恭喜你在提问之前清楚地阅读了Help Center:这是一个很好的第一个问题。清晰,简洁,精确地包含必要的细节,没有一堆多余的废话。如果可以的话,我会支持你的问题 5 次。干得好! 【参考方案1】:

您提供的示例函数已经是纯函数式的。当我们谈论函数纯度时,我们实际上是在谈论函数的属性是referentially transparent

如果一个表达式可以用它的值替换而不改变程序的效果,那么它就是引用透明的。举个简单的例子,想象一下这个函数:

let add2 x = x + 2

现在,只要值 add2 2 出现在我们的程序中,我们就可以替换值 4 而不会改变程序的行为。

现在想象一下,我们在打印到控制台的函数中添加了一些额外的行为:

let add2Print x =
    printfn "%d" x
    x + 2

虽然函数的结果和以前一样,但我们不能再在不改变程序行为的情况下用值4 执行值替换,因为我们的函数具有打印到控制台的额外副作用。

这个函数不再是引用透明的,因此不是一个纯函数。


let rec greatestCommonFactor a b =
    if a = 0 then b
    elif a < b then greatestCommonFactor a (b - a)
    else greatestCommonFactor (a - b) b

看看你提供的这个函数,它的执行没有任何副作用。对于给定的输入ab,我们将始终得到相同的输出值,因此这已经是一个纯函数了。

需要明确的是,在函数式编程中包含条件的函数绝对没有问题。但是,我们通常使用模式匹配而不是 if/elif/else 表达式,但在您描述的示例中,这纯粹是风格上的。使用模式匹配的函数的替代表达式是:

let rec greatestCommonFactor a b =
    match a with
    |0 -> b
    |a' when a' < b -> greatestCommonFactor a' (b - a')
    |a' -> greatestCommonFactor (a' - b) b

【讨论】:

所以条件无关紧要?我的印象是在功能范式中优先考虑消除条件。比如使用 lambdas 代替它们。 @Zach 一些函数式语言倾向于简洁的风格,但条件仍然存在。甚至 Haskell 也有 if 关键字,不过,就像在 F# 中一样,您更倾向于使用模式匹配而不是 ifthen @Zach 不,条件绝对不重要。函数式编程中的条件通常是通过模式匹配而不是通过 if/elif/else 表达式来处理的,但在您在这里介绍的情况下,它纯粹是风格。 非常感谢你们两位的澄清。 @Zach 我还没有看到这里提到的是,在函数式语言中我们通常有 if 表达式,即 if 和 else(甚至 else-if)分支 必须 在每个分支上返回相同的类型。这是使引用透明性成为可能的限制。

以上是关于纯函数式编程的主要内容,如果未能解决你的问题,请参考以下文章

纯函数式编程中的“价值”是啥?

纯函数式编程

纯函数:函数式编程入门

函数式编程

函数式编程

Swift函数式编程八(纯函数式数据结构)