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

时间:2012-11-27 22:53:31

标签: functional-programming lambda-calculus purely-functional

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

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

5 个答案:

答案 0 :(得分:15)

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

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

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

答案 1 :(得分:14)

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

这会给你一些非常奇怪的东西,因为你唯一能做的就是把它应用到别的东西上。你什么时候去观察什么?您有一些价值f,想要了解它的一些信息,您唯一的选择就是应用一些值x来获取f x,这是另一个功能,唯一的选择就是申请将其转换为另一个值y,以获取f x y等等。

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

purePlus = \zero succ natCase -> 
   let plus = \m n -> natCase m n (\m' -> plus m' n)
   in plus (succ (succ zero)) (succ (succ zero))

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

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

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

答案 2 :(得分:6)

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

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

-- | 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

该功能以具体列表为起点,但这不是必需的。您可以使用纯函数构建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

最后一个函数使用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

这种转换基本上可以在任何类型上完成,因此从理论上讲,你可以摆脱Haskell中的所有“值”类型,并且只保留()类型,(->)IO类型构造函数,return的{​​{1}}和>>=以及一组合适的IO基元。这显然是hella不切实际 - 而且会表现得更差(尝试写IO来品尝)。

答案 3 :(得分:6)

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

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

对于函数式语言, 没有实用语言是“纯函数式”的,因为语言可以操作的每个值都是一个函数。用这种语言编程肯定是可能的。 lambda演算的最基本版本没有任何不是函数的概念,但你仍然可以通过提出表示你想要计算的东西的方式对它们进行任意计算作为函数。 2

虽然lambda演算的简单性和极简主义对于证明关于编程的事情往往很有用,但实际上用这种“原始”编程语言编写实质程序是很尴尬的。数字等基本内容的函数表示在实际物理机器上实现效率也很低。

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

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


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

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

3 这也不是基础。你可以设计一种纯粹的面向对象的语言,这种语言在这个意义上是纯粹的。无论如何,我倾向于把大部分的OO代码写成纯粹的。

4 如果这看起来很钝,你可能会反映出“功能”,“对象”和“语言”这两个词在其他语境中的含义也大相径庭。

答案 4 :(得分:0)

getChar :: IO Char是否有功能? Haskell报告没有为我们提供定义。但它声明getChar 是一个函数(请参阅here)。 (好吧,至少我们可以说它是一个函数。)

所以我认为答案是

除了“一切都是功能”之外,我认为没有正确的“功能”定义。 (什么是“正确定义”?好问题......)考虑下一个例子:

{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Applicative

f :: Applicative f => f Int
f = pure 1

g1 :: Maybe Int
g1 = f

g2 :: Int -> Int
g2 = f

f是函数还是数据类型?这取决于。