函数式编程公理

时间:2017-05-05 08:48:02

标签: function clojure functional-programming reduce higher-order-functions

我用 Clojure 学习函数式编程,并希望加深对函数范式的理论理解(不仅仅是Clojure的语法)。

我正在寻找公理公式每种功能技术如递归,映射,减少,缺点,第一次休息彼此相关,它是可衍生的/可组合的,并且是一切背后的最终公理。

例如,我意识到map只能使用recurfirstrestcons函数来实现,当然还有映射函数本身传递给map

之后,我还意识到map也可以使用reduce来实现,并且可以使用recurfirstrest再次实现reduce。此外filter也可以reduce实施。

我觉得我开始围绕功能编程,但仍然很难看出哪些是最终的构建块,即哪个是抽象的最小集合关键字组成任意函数。使用map示例,第二种方法使用少一个抽象来定位相同的目标。那么,什么是功能范式的最终公理,以帮助我看到大局?

3 个答案:

答案 0 :(得分:5)

从lambda(在clojure中称为fn),你可以得到任何其他东西。例如,让我们执行consfirstrestfn派生的经典练习:

(defn cons [x y]
  (fn [f]
    (f x y)))

(defn first [coll]
  (coll (fn [x y] x)))

(defn rest [coll]
  (coll (fn [x y] y)))

因此,如果你想要一套用于函数式编程的公理,那么只有一个公式:lambda是最终的公理。有关如何完成其​​他功能的派生的详细信息,请参阅以下文章:

  • 经典的Lambda the Ultimate论文。
  • Programming with Nothing,这是一种更新的方法。这使用Ruby语法,但它并不重要,因为它使用的唯一语言特性是lambda。
  • SICP还有一节关于从lambda派生car / cdr / cons,作为解释抽象障碍价值的一部分:实施并不重要,只要它满足你的合约#&# 39;已建立。当然,如果您对编程的基础感兴趣,那么SICP通常是一本很好的读物。

从评论中可以看出,对这个答案存在很多困惑;我没有为那些以前没见过的人解释过它。

我们的想法不是重新实现clojure的所有内置第一/休息功能,这些功能是适用于各种序列的高级多态事物。相反,我们通过满足合同来实现三个cons / first / rest函数,这些函数可以一起工作以允许您构建集合

(= x (first (cons x y)))
(= y (rest (cons x y)))

可以构建更复杂的东西,比如clojure的实际第一个/休息只有lambda,但你必须首先发明一个完整的类型系统,以便更多地参与其中。

这是一个示例repl会话,描述了本练习的目的:

(defn cons [x y]
  (fn [f]
    (f x y)))

(defn first [coll]
  (coll (fn [x y] x)))

(defn rest [coll]
  (coll (fn [x y] y)))
user> (def integers (cons 0 (cons 1 (cons 2 (cons 3 nil)))))
#'user/integers
user> integers
#object[user$cons$fn__2108 0x3fb178bd "user$cons$fn__2108@3fb178bd"]
user> (first integers)
0
user> (first (rest (rest integers)))
2

答案 1 :(得分:1)

首先要了解大多数函数式语言中列表的constructed如何,这意味着,为什么将列表视为firstrest非常有意义。这种递归定义是理解用于更改它们的递归机制的关键。

我第一次尝试地图/过滤/折叠等的方式实际上是通过haskell,它具有表达事物类型的好处。这对初学者来说很有意义,至少对我而言。

例如,map将签名(a -> b) -> [a] -> [b]读为:如果您的某个函数采用类型a并将其转换为b类型,并且您给出了类型为a的列表,然后map会返回一个类型为b的列表。

您应该花时间理解的是foldleftright),其中reduce是打字的特例世界。一旦你准备好了,我建议你去看看好的A tutorial on the universality and expressiveness of fold

我强烈建议您尝试实施您提到的所有内容,您对这些基本构建块及其依赖项的理解将会大大改善。根据{{​​1}}实施reduce(和折叠),在recurmap方面实施filter take recur等等

答案 2 :(得分:1)

我认为你不能找到一组类似于概率论的简单公理。对于概率,只有3个基本公理:

    每个事件A
  • P [A]> = 0
  • P ["任何事件"] = 1
  • P [A或B] = P [A] + P [B]如果A& B是相互排斥的

令人惊讶的是,一切都在概率和范围内。统计数据可以从这三个基本假设中得出。

" 功能编程"没有那么明确。事实上,几乎所有关于这个主题的书都是从观察到的,如果你问过100名专家"要定义函数式编程,您将收到100个互不兼容的答案。这句话只是部分开玩笑。

关于功能性编程,你唯一能说的就是它强调功能而不是传统功能,而非功能性编程功能#34;语言。这实际上更像是一个"目标"对于函数式语言或函数式编程风格而不是是/否观察。

功能编程的目标与以往一样:通过更简单的方式节省成本&可靠性。当然,每种语言和从计算开始以来的技术就有了同样的游戏计划。 FP旨在通过以下方式实现它:

  • 减少使用可变变量
  • 增加使用功能而非手动循环

请注意,它表示"减少" &安培; "增加"而不是"仅" &安培; "从未&#34 ;.决定这意味着什么是判断,并且答案将根据手头的问题和你问的人而改变。

请记住这两个问题&人们随着时间而变化。答案是"最好的"今天在成本,复杂性,效率,可维护性等方面的权衡可能不会是最好的"在一个月或一年内回答问题,人员,工具,硬件,价格等随着时间的推移而变化。

记住科学校长。它迫使你尝试(实验),而不仅仅是思考它们(理论)。所以你必须要做一些事情并观察结果。

在软件中,这意味着以2种(或更多种)方式解决问题,并比较优缺点。每种方法的缺点。