在纯函数式语言中,数据(字符串,整数,浮点数)也只是函数吗?

Jam*_*tos 12 functional-programming lambda-calculus purely-functional

我正在考虑像Ruby这样的纯面向对象语言,其中包括数字,int,浮点数和字符串在内的所有内容本身就是对象.这与纯函数式语言是一回事吗?例如,在Haskell中,Numbers和Strings是否也起作用?

我知道Haskell基于lambda演算,它将所有内容(包括数据和操作)表示为函数.对我来说,"纯粹的函数式语言"将所有内容都作为一个函数进行建模,并且保持一个函数最常返回相同输出且具有相同输入且没有状态的定义,这似乎是合乎逻辑的.

wrh*_*all 15

理论上可以考虑一下,但......

就像在Ruby中一样,并不是所有东西都是对象(例如,参数列表不是对象),而不是Haskell中的所有东西都是函数.

有关更多参考,请查看这个简洁的帖子:http://conal.net/blog/posts/everything-is-a-function-in-haskell

  • 我认为Ruby /纯面向对象语言的类比有点缺陷,因为Ruby中的所有内容都不是一个对象,每个*value*都是一个对象 - 这就是通常定义"纯面向对象"这个术语的方式.在Haskell或一般的纯函数语言中也是如此,即并非每个值都是函数. (6认同)
  • 正是我要发布的链接 (2认同)
  • +1始终值得链接到Conal Elliott所说的内容. (2认同)

luq*_*qui 14

@wrhall给出了一个很好的答案.然而,你在某种程度上是正确的,在纯粹的lambda演算中,所有东西都是一个函数是一致的,并且语言是Turing-complete(能够表达Haskell等的任何纯计算).

这给了你一些非常奇怪的东西,因为你唯一能做的就是把它应用到别的东西上.你什么时候去观察什么?你有一些价值f,想知道它的一些东西,你唯一的选择就是应用它x来获取一些值f x,这是另一个函数,唯一的选择是将它应用于另一个值y,得到f x y等等.

我经常将纯粹的lambda演算解释为关于不是函数的事物的转换,而只能表达函数本身.也就是说,我可以创建一个函数(带有一些Haskelly语法糖用于递归和let):

purePlus = \zero succ natCase -> 
   let plus = \m n -> natCase m n (\m' -> plus m' n)
   in plus (succ (succ zero)) (succ (succ zero))
Run Code Online (Sandbox Code Playgroud)

在这里,我已经表达了计算,2+2而不需要知道有非函数这样的东西.我只是将我需要的东西作为我所定义的函数的参数,这些参数的值可以是教会编码,也可以是"真实"数字(无论这意味着什么) - 我的定义并不关心.

你可以想到Haskell的相同之处.没有特别的理由认为有些东西不是功能,也没有特别的理由认为一切都是功能.但是Haskell的类型系统至少会阻止你对一个数字应用一个参数(fromInteger现在任何想到的人都需要保持他们的舌头!:-).在上面的解释中,这是因为数字不一定被建模为函数,因此您不必将参数应用于它们.

如果现在还不清楚,这整个答案在某种程度上是一个技术/哲学的题外话,你问题的简单答案是"不,不是一切都是功能语言的功能".函数是你可以应用参数的东西,就是全部.


Lui*_*las 6

在这个问题上有一个非常不同的角度:Haskell中的各种数据都可以用一种称为Church编码的技术表示为函数.这是一种控制反转形式:不是将数据传递给使用它的函数,而是将数据隐藏在一组闭包中,并使用它来传递描述如何处理这些数据的回调.

例如,任何使用列表的程序都可以转换为使用函数而不是列表的程序:

-- | A list corresponds to a function of this type:
type ChurchList a r = (a -> r -> r)  --^ how to handle a cons cell
                   -> r              --^ how to handle the empty list
                   -> r              --^ result of processing the list

listToCPS :: [a] -> ChurchList a r
listToCPS xs = \f z -> foldr f z xs
Run Code Online (Sandbox Code Playgroud)

该功能以具体列表为出发点,但这不是必需的.您可以使用ChurchList纯函数构建函数:

-- | The empty 'ChurchList'.
nil :: ChurchList a r
nil = \f z -> z

-- | Add an element at the front of a 'ChurchList'.
cons :: a -> ChurchList a r -> ChurchList a r
cons x xs = \f z -> f z (xs f z)

foldChurchList :: (a -> r -> r) -> r -> ChurchList a r -> r
foldChurchList f z xs = xs f z

mapChurchList :: (a -> b) -> ChurchList a r -> ChurchList b r
mapChurchList f = foldChurchList step nil
    where step x = cons (f x)

filterChurchList :: (a -> Bool) -> ChurchList a r -> ChurchList a r
filterChurchList pred = foldChurchList step nil
    where step x xs = if pred x then cons x xs else xs
Run Code Online (Sandbox Code Playgroud)

最后一个函数使用Bool,但当然我们也可以Bool用函数替换:

-- | A Bool can be represented as a function that chooses between two 
-- given alternatives.
type ChurchBool r = r -> r -> r

true, false :: ChurchBool r
true a _ = a
false _ b = b

filterChurchList' :: (a -> ChurchBool r) -> ChurchList a r -> ChurchList a r
filterChurchList' pred = foldChurchList step nil
    where step x xs = pred x (cons x xs) xs
Run Code Online (Sandbox Code Playgroud)

这种转变可以做的基本上任何类型的,所以在理论上,你可以摆脱在Haskell所有的"值"类型的,并且只保留()类型,(->)IO类型构造,return以及>>=用于IO和一套合适的IO基元.这显然是hella不切实际 - 并且它会表现更差(尝试写作尝试tailChurchList :: ChurchList a r -> ChurchList a r).


Ben*_*Ben 6

"纯功能"中的"纯"是指"无副作用"的纯度.当人们谈论"纯粹的面向对象语言"时,它与"纯粹"的含义几乎没有关系,这只是意味着语言纯粹(仅)操纵对象.

原因是pure-as-only-only是用于对面向对象语言进行分类的合理区别,因为有些语言如Java和C++,它们显然具有与对象没有多少共同之处的值,还有像Python和Ruby这样的语言,可以说每个值都是一个对象1

而对于功能性语言,还有没有实际的语言这是在这个意义上,所有的语言可以操纵值是一个函数"纯函数".用这种语言编程当然是可能的.lambda演算的最基本版本没有任何不是函数的概念,但你仍然可以通过提出用函数表示你想要计算的东西的方法来对它们进行任意计算.2

不过,虽然演算的简单性和极简主义往往是伟大的证明的事情有关规划,在这样一个"原始"的编程语言实际编写的许多方案是尴尬.数字等基本事物的函数表示在实际物理机器上实现的效率也很低.

但是,语言之间存在着非常重要的区别,它鼓励功能风格,但允许任何地方无法解决的副作用,以及实际强制你的功能是"纯粹"功能的语言(类似于数学函数).面向对象的编程非常强调使用不纯的计算3,因此没有实用的面向对象编程语言在这个意义上是纯粹的.

因此,"纯函数式语言"中的"纯粹"意味着与"纯粹的面向对象语言"中的"纯粹"不同.4在每种情况下,"纯粹与非纯粹"的区别是对另一种语言完全不感兴趣的区别,因此没有非常强烈的动机来标准化该术语的使用.


1我所知道的所有"纯面向对象"语言中都有可供选择的案例,但这并不是很有趣.很明显,对象隐喻在语言中更进一步,其中语言1是某个类的实例,并且该类可以是子类,而不是在1除了对象之外的语言中.

2 无论如何,所有计算都是关于表示的.计算机对数字或其他任何事物都不了解.它们只有我们用来表示数字的位模式,以及碰巧与数字操作相对应的位模式操作(因为我们设计它们就是这样).

3这也不是根本.您可以设计一种纯粹的面向对象语言,在这种意义上是纯粹的.无论如何,我倾向于将大部分的OO代码写成纯粹的.

4如果这看起来很钝,你可能会反映出术语"功能","对象"和"语言"在其他情境中的含义也大相径庭.