Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 函数式编程的原则、最佳实践和设计模式_Design Patterns_Functional Programming_Principles - Fatal编程技术网

Design patterns 函数式编程的原则、最佳实践和设计模式

Design patterns 函数式编程的原则、最佳实践和设计模式,design-patterns,functional-programming,principles,Design Patterns,Functional Programming,Principles,在用函数式编程语言编写代码时,是否有任何已知的原则、最佳实践和设计模式可以遵循 不要遵循原则,跟着你的鼻子走。保持函数简短。寻找降低代码复杂性的方法,这通常意味着但不一定意味着最简洁的代码。了解如何使用内置的高阶函数 在编写函数后立即重构并减小其代码大小。这节省了时间,因为明天你不会想到问题和解决方案。有折叠、展开、地图等 我认为最好的做法是使用他们的行为,因为他们很容易对自己的行为进行推理,而且他们经常交流一个函数的目的(例如,看看著名的和对比的大一和大一的人,还有教授)。约翰·休斯给出了为什

在用函数式编程语言编写代码时,是否有任何已知的原则、最佳实践和设计模式可以遵循

不要遵循原则,跟着你的鼻子走。保持函数简短。寻找降低代码复杂性的方法,这通常意味着但不一定意味着最简洁的代码。了解如何使用内置的高阶函数


在编写函数后立即重构并减小其代码大小。这节省了时间,因为明天你不会想到问题和解决方案。

有折叠、展开、地图等

我认为最好的做法是使用他们的行为,因为他们很容易对自己的行为进行推理,而且他们经常交流一个函数的目的(例如,看看著名的和对比的大一和大一的人,还有教授)。约翰·休斯给出了为什么懒惰和高阶(一等)的好动机。函数提供了许多函数性较差的语言

在Haskell的背景下,我认为这本书在习语、抽象和类型类等方面提供了一些很好的实用建议。这个方法也总是有用的。核心的、非常抽象的类型类可以看作是设计模式,除非它们是由编译器/类型系统和语言的一部分强制执行的(如果您学习如何使用它们)


在Lisp的上下文中,Paul Graham写了一本名为《关于Lisp()的书》,他在书中展示了函数式语言是创建自定义编程语言然后用它编写程序的理想选择。因此,嵌入式领域特定语言本身就是一种设计模式。

最佳实践:使用代数数据类型,并利用模式匹配编译器的穷尽性检查。特别是,

  • 永远不要在顶层匹配通配符模式

  • 设置编译器选项,使模式匹配中缺少的大小写是错误,而不是警告

设计模式:让编译器为您的函数推断类型,并确保这些类型与您期望的完全相同。如果类型更多态或更少多态,请找出原因

例如,如果您正在Haskell中编写排序函数,则

Ord a => [a] -> [a]
如果你的类型是

Num a => [a] -> [a]

那么,事情就糟透了


最佳实践:一旦您向编译器确认类型如您所期望的那样,请为每个顶级函数放置一个显式类型签名。(或者,如果您使用的是ML或Caml,请编写一个显式接口。)设置编译器选项,使缺少签名的值触发错误。

设计模式:让类型指导您的编码

  • 找出要返回的类型

  • 知道某些类型构造函数带有某些语法,并利用它使所需的类型更小。以下是两个例子:

    • 如果您试图返回函数类型
      T1->T2
      ,那么编写总是安全的

      \ x -> ...
      
      现在,在body中,您正试图生成一个类型为
      T2
      的值,这是一个较小的类型,另外您还获得了一个类型为
      T1
      的额外值
      x
      ,这可能会使您的工作更轻松

      如果lambda被证明是不必要的,您可以在以后减少它

    • 如果您试图生成一对类型
      (T1,T2)
      ,则始终可以尝试生成类型
      T1
      x
      值和类型
      T2
      y
      ,然后形成该对
      (x,y)
      。同样,您已经将问题简化为具有较小类型的问题

  • 一旦类型尽可能小,请查看作用域中所有let-bound和lambda-bound变量的类型,并查看如何生成所需类型的值。通常,您希望对所有函数使用所有参数;如果你没有,一定要解释原因


  • 在许多情况下,尤其是在编写多态函数时,这种设计技术可以将复杂函数的构造减少到只有一个或两个选择。类型指导程序的构造,因此编写正确类型的函数的方法很少,而且通常只有一种方法不是明显错误的。

    我的回答可能有点模糊:努力使代码美观,这是最重要的方面。致David Gelernter:

    美在计算中比任何其他技术领域都重要,因为软件是如此复杂。美是对复杂性的终极防御

    布莱恩·克尼汉:

    控制复杂性是计算机编程的本质

    如果您追求这一目标,它将引导您编写易于阅读和理解(这一点非常重要)的代码,这些代码被拆分为具有明确目的的小型紧凑部分。它将引导你学习如何用特定的语言以最好的方式表达你的想法


    (所有这些不仅仅适用于函数式语言,但在函数式语言中编写漂亮的代码要容易得多。)

    DRY(不要重复)确实有助于降低复杂性。一个地方改变要比两个地方容易得多。在你重构之前,最好你有你的单元测试用例,否则可能是开始编写它们的好时机。这就是免费的意义,对吗?@Jared:我想说“免费定理”更多的是代数定律的来源,你可以在程序计算时使用。给定多态函数的类型,有一个“自由定理”,它是一个遵循的代数定律。我不经常使用这些模式,但我一直都在使用类型定向编码。您可以使用
    -fwarn complete patterns
    结合
    -Werror
    在缺少案例时获得致命错误。它也可以被给予
    \ x -> ...