2009-09-25 83 views
21

我正在阅读关于Haskell的this教程。他们定义函数组合如下所示:分别提供Haskell函数组合

(.)      :: (b->c) -> (a->b) -> (a->c) 
f . g     = \ x -> f (g x) 

没有例子,我相信会开导我,给正在这里定义的内容。

有人可以提供一个简单的例子(解释)如何使用函数组合?

回答

38

功能组合是一种将两个功能“组合”为一个功能的方法。这里有一个例子:

假设你有以下功能:

even :: Int -> Bool 
not :: Bool -> Bool 

并要使用两个以上定义自己的myOdd :: Int -> Bool功能。

最明显的方式做到这一点是:

myOdd :: Int -> Bool 
myOdd x = not (even x) 

但是,这可以更简洁地使用函数组合来实现:

myOdd :: Int -> Bool 
myOdd = not . even 

myOdd函数的行为完全一致,但第二一个是通过将两个功能“粘合”在一起而创建的。

这个特别有用的场景是消除了对显式lambda的需求。 E.g:

map (\x -> not (even x)) [1..9] 

可以被改写为:

map (not . even) [1..9] 

短一点,错误少的房间。

+0

你怎么不需要在定义中显示输入参数?例如。你怎么不写'myOdd x = not。甚至x'? – unclerojelio

+2

@unclerojelio它被称为无点风格。根据给定参数的结果(“给定'x”,'myOdd'返回与'(not。even)x'“相同的值)来定义'myOdd',它是根据它实际是(“'myOdd'是'not'由'even'构成时的结果]”)。 – chepner

13

组合物的fg是首先施加g它的参数,那么fg返回的值的函数。然后它返回f的返回值。

这个身份可以有所启发:

f (g x) = (f . g) x

如果你有一个Java/C的背景下,考虑这个例子:

int f(int x); 
int g(int x); 
int theComposition(int x) { return f(g(x)); } 
+0

+1等效 – outis

4

HaskellWiki page on function composition:

desort = (reverse . sort) 

现在desort是一个反向排序列表的函数。基本上,desort将它的参数提供给sort,然后将返回值从sort提供到reverse,返回值为。所以它对它进行排序,然后它反转排序的列表。

7

这个例子是人为的,但假设我们有

sqr x = x * x 
inc x = x + 1 

,我们希望编写计算x^2 + 1的功能。我们可以写

xSquaredPlusOne = inc . sqr 

(这意味着

xSquaredPlusOne x = (inc . sqr) x 

这意味着

xSquaredPlusOne x = inc(sqr x) 

由于f = INC和g = SQR)。

26

有趣的一面。功能组成相当于逻辑中的三段论:

所有的人都是凡人。苏格拉底是一个男人。因此,苏格拉底是致命的。

甲三段式构成两个材料影响到一个:

(Man => Mortal), (Socrates => Man), therefore (Socrates => Mortal) 

因此...

(b -> c) -> (a -> b) -> (a -> c) 

...这是.功能的类型。

3

功能组合是将两个或更多功能链接在一起的一种方式。它通常被比作外壳管道。例如,在Unix风格的外壳,你可能会喜欢写东西

cat foo.txt | sort -n | less 

这将运行cat,其输出馈送给sort,并从输出馈送到less

严格来说,这就像Haskell $运营商。你可能会写如

sum $ sort $ filter (> 0) $ my_list 

请注意,与shell示例不同,它从右到左读取。所以我们以my_list作为输入,然后我们运行filter越过它,然后我们sort呢,然后我们计算出它的sum

函数组合运算符.做了类似的操作。以上示例产生号码;下面的例子产生功能

sum . sort . filter (> 0) 

请注意,我们实际上并没有养活一个列表到这一点。相反,我们刚刚创建了一个新函数,我们可以为该函数提供几个不同的列表。例如,您可以命名此功能:

my_function = sum . sort . filter (> 0) 

或者你可以把它作为一个参数传递给另外一个函数:

map (sum . sort . filter (> 0)) my_lists 

基本上你可以使用它的任何地方,你可以使用任何其他种类的功能。这只是一种快速而可读的说法,“我想将这些功能连在一起”。