2009-09-25 106 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 

基本上你可以使用它的任何地方,你可以使用任何其他種類的功能。這只是一種快速而可讀的說法,「我想將這些功能連在一起」。