guidelines/practices/rules 完全符合功能范式的详尽清单是什么?

What is the exhaustive list of guidelines/practices/rules to fully conform with functional paradigm?

我已经开始使用 Kotlin,但我感觉到自己在编程方式上的局限性。我的问题是我仍然认为 Java 因此风格仍然是势在必行的,我的问题是所有函数式编程狂热者,我相信这对所有处于最开始阶段并且还需要 'brake' 他们的大脑重新开始构建它;离开舒适区并开始思考伪而不是 "whatever is your first language"。我相信经验丰富的多语言开发人员有可能将这些概念细化为 关于什么使您的程序以完全实用的方式编写以及什么违反范式的简单建议。我不知道所有的怪癖,但请不要犹豫,包括我可能不知道的普遍接受的术语(我总是可以查找)。在这一点上,我需要这套规则来让自己先受苦,而不是打破它们,但后来我知道我会感受到它,分析指导方针并理解它们是如何的worse/better这当然是我自己的功课。

这些准则的示例如下:

我希望这个答案能给我长期的参考,让我把自己置于极端条件下,每当我感到不舒服时,我就不再逃避 OOP。现在,当我看 Kotlin 时,我明白了我应该如何思考问题,它是关于意图而不是一种语言或另一种语言强加的结构。意图总是可以转换为您选择的语言,并得到适用于该语言的设计模式的支持,但要找到中间地带,我需要先把自己从舒适区监禁起来。

  • 避免像瘟疫这样的可变状态

    使用函数式编程的要点之一,可能是主要的一点,是避免所有小陷阱、错误和使用可变状态时需要处理的问题。你应该尽一切可能避免改变状态。例如,不要在需要更新计数器变量的地方使用 C 风格的 for 循环,而是使用 map 和其他高阶函数来抽象出迭代模式。这也意味着如果可以避免的话,永远不要更改变量的值。相反,您应该将几乎所有变量(最好是所有变量)定义为常量,并使用函数从它们计算新值而不是改变它们。

  • 避免像瘟疫一样的副作用

    可变状态的丑表亲,副作用。副作用意味着除了在函数中取值和 returning 值之外的任何事情。如果该函数打印数据、改变全局变量、向线程发送消息,或任何除了简单地获取其参数、从中计算出一个值并 returning 一个值之外的任何东西,那么该函数就会产生副作用。副作用很重要(见下一个要点),但如果你经常使用它们,它们就无法追踪。想想每个人如何告诉你在命令式编程中避免使用全局变量。函数式编程更进一步,试图避免所有的副作用。您的程序的大部分应该由 纯函数 组成。 (向前看)

  • 当你需要使用副作用时,请控制它们。

    是的,我只是告诉您 运行 远离副作用。然而,没有某种副作用的程序是没有用的。图形用户界面?副作用。音频输出?副作用。打印到 shell?副作用。所以如果你想构建有用的东西,你就无法真正摆脱副作用。 相反,您应该做的是编写您的代码,以便所有有副作用的代码都位于一个薄层中,该层主要调用纯函数,然后使用这些纯函数调用的结果来执行所需的副作用。

  • 尽可能使用纯函数.

    这是前一点的反面。 纯函数是一个没有副作用并且不会改变任何东西的函数。它只能接受参数和 return 一个值。你应该经常使用这些。例如,与其在计算内容的函数中进行日志记录,不如使用纯函数构造日志字符串,然后让副作用层调用这些纯函数,调用更多纯函数以格式化日志字符串成一个完整的日志,然后从你的副作用层输出日志本身。

  • 使用高阶函数构建代码.

    高阶函数在某种程度上是使函数式编程工作的粘合剂。高阶函数是将一个或多个函数作为参数的函数 and/or returns 函数。高阶函数的强大之处在于它们可以以声明的方式封装您将在命令式程序中使用的许多模式。例如,让我们看一下最常见的三个高阶函数:

    map 是一个函数,它接受一个函数和一个值列表,将其函数参数应用于每个值,return 是一个包含结果的新列表。 map 封装了以声明方式遍历列表对每个值执行操作的整个模式。

    filter 是一个函数,它接受一个函数,该函数 return 是一个布尔值和一个值列表,将其函数参数应用于每个值, return 是一个仅包含的列表其函数参数 returns true 的那些值。它以声明的方式封装了从列表中选择结果的整个模式。

    reduce,也称为 fold,采用初始值、二元函数和值列表。它使用其函数参数将初始值与列表的第一个值组合,然后将结果与列表的下一个值组合并继续这样做,直到将列表减少到只有一个值。它封装了从值列表中获取聚合值的整个模式。

    这绝不是高阶函数的详尽列表,但这三个是最常见的。我希望这足以说明如何以声明方式仅使用函数来构建需要大量跟踪变量的代码。如果你能很好地使用这些高阶函数,你可能再也不需要 forwhile 循环了。

这绝对不是详尽的函数式编程实践列表,但我认为大多数函数式程序员会同意这五个准则构成函数式编程的核心。如果你真的想学习如何应用这些,我的建议是学习一门函数式编程语言,比如Haskell,这样你就被迫放弃命令式范式,而是学习如何在功能上构建事物。我会推荐很棒的 Haskell Programming from First Principles as a starting resource if you choose to go this way. In case you don't want to/can't put down the cash, Brent Yorgey's Haskell course at UPenn 也是一个很棒的免费资源。