4

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

我想找公理公式递归,图中的每个功能的技术如何,减少,利弊,第一ANS其余涉及对方,这是衍生/从该组合的,并且其一切背后的终极公理。

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

在那之后,我也意识到map可以使用reduce也实现,并再次减少可使用recurfirstrest实施。 filter也可以用reduce来实现。

我觉得我开始换我周围的函数式编程的头,但它仍然是很难看到,这是最极致的建筑块,即这是最低组的抽象关键字组成任意的功能。在地图示例中,第二种方法使用一个较少的抽象来定位相同的目标。那么,功能范式的一些最终公理是如何帮助我看到大局的?

+1

在这种情况下,我会建议你看看这本书:https://mitpress.mit.edu/books/little-schemer这是一个了不起的FP介绍,告诉你如何使用一个基本的数字的元素。经典的[SICP](https://mitpress.mit.edu/sicp/full-text/book/book.html)也可以提供很多帮助。他们两个都雇用lisp(准确地说,方案),所以很容易将你的理解转化为clojure – leetwinski

+0

函数式编程大部分根源于Lamda微积分,核心公理如下面的amalloy所述。 –

+0

不要忘了,'map'也可以替换为'for' –

回答

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 the Ultimate论文。
  • Programming with Nothing,更新的方法。这使用Ruby语法,但它并不重要,因为它使用的唯一语言功能是lambda。
  • SICP也有一个关于从lambda派生car/cdr/cons的章节,作为解释抽象障碍价值的一部分:只要满足您所建立的合约,实现并不重要。当然,如果你对一般编程的基础感兴趣,那么SICP就是一个很好的阅读。

它从注释中好像有很多关于这个答案的困惑;我的错是因为没有为以前没见过的人解释过。

这个想法并不是重新实现所有clojure的内置第一个/休息功能,这是先进的多态的东西,适用于各种序列。相反,我们实现三个缺点一起工作,让你建立的集合,通过满足合同/首/休息函数

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

可以构建更复杂的东西像Clojure的实际第一/休息只有拉姆达,但你必须首先发明一个完整的类型系统,所以它涉及更多。

这里的描述一下这个演习意在展示一个例子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 "[email protected]"] 
user> (first integers) 
0 
user> (first (rest (rest integers))) 
2 
+0

这看起来很有希望,但即使我看过clojure文档,我也不明白。这些书中解释了这个“典型例子”吗?集合如何作为一个函数使用?我在clojure REPL中试过这个,并得到错误'IllegalArgumentException Key must be integer'。 –

+0

我也对这里发生的事情感到困惑。您正在使用函数为集合编制索引。 – Carcigenicate

+0

我的编辑改进了一些东西吗?先休息一下,没有错;相反,预期用途显然不明确。 – amalloy

1

开始通过了解清单是如何在最实用的语言,意思constructed,为什么让这么多的意义看清单如firstrest。这个递归定义是理解你改变它们的递归机制的关键。

我首先通过haskell实现了映射/过滤/折叠等方式,它具有表达事物类型的好处。这对初学者来说很有意义,至少对我来说是这样。

例如,map有读作签名(a -> b) -> [a] -> [b]:如果你有一个函数,它接受一个类型a,并把它变成一个类型b,你给a类型的列表,然后地图只会返回您的列表键入b

你应该把你的时间在了解一个是fold(包括leftright),其中reduce是在一个类型的世界的一个特例。一旦你感觉准备好了,我会建议你重新考虑一下你所提到的一切,你对这些基本构建模块和它们的依赖关系的理解会得到很大的改善。实现减少(两者倍)在recur方面,实施mapfiltertake等在国内外的recur方面reduce

+0

好的练习,但是'foldr'在Clojure中比在Haskell中有用得多,因为我们缺乏持久的懒惰。尝试自己实现它,然后在大型集合上实际使用它。 '或:: [Bool] - > Bool;或= foldr(||)由于短路,False对于大集合非常适用,但Clojure中的版本并不好。 – amalloy

+0

绝对同意你@amalloy。我认为这是一个很好的练习,可以帮助你理解折叠是什么以及刚开始学习它们的人有何不同。 – Shlomi

1

我不认为你可以找到一组简单的公理类似于概率理论,例如。对于概率,仅存在3个基本公理:

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

这是很令人惊讶的是一切都在概率统计&可以从这三个基本假设得出。

函数式编程”的定义不太明确。事实上,几乎所有关于此主题的书都以观察结果开始,如果您要求100位“专家”定义函数式编程,您将收到100个互不相容的答案。这种说法只是部分地开玩笑。

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

函数式编程的目标与往常一样:通过更简单的可靠性实现成本节省&。当然,自计算开始以来,每种语言技术都有相同的游戏计划。 FP的目的主要是实现它:

  • 减少使用可变变量的
  • 增加使用功能,而不是手动循环

注意,它说:“减少” &“增加”,而不是“只有“&”从不“。决定这意味着什么是一个判断呼叫,答案会根据手头和你问的人的问题而改变。

请记住,这两个问题&人随时间变化。如今,在成本,复杂性,效率,可维护性等方面进行“最佳”平衡的答案在问题,人员,工具,硬件,价格等变化时可能不是一个月或一年中的“最佳”答案随着时间的推移。

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

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