函數式編程之-組合函數

組合

函數式編程的核心在於組合,其中之一就是如何組合函數。咱們在Currying一文就提到過組合,咱們當時是這樣描述的:只有一個輸入和一個輸出的函數才能完成組合,固然並非全部的函數都只有一個輸入,Currying能夠幫助咱們把多個輸入參數的函數變成只有一個輸入的函數。
那麼到底什麼是組合,怎麼組合?
給定下面的兩個函數:

組合上面的兩個函數:

變成下面的函數:

看個例子:編程

let add1 x = x + 1 
let multiply2 x = x * 2
let compose g f x = f(g(x))

對應的函數類型爲:數組

add1 : x:int -> int
multiply2 : x:int -> int
compose : g:('a -> 'b) -> f:('b -> 'c) -> x:'a -> 'c

經過compose函數來把add1和multiptly2組合起來:函數式編程

let add1ThenMultiply2 x = compose add1 multiply2


從而獲得新的函數:
函數

let result = add1ThenMultiply2 10


既然compose這個函數在F#這麼經常使用,不如定義一個操做符>>來表示:3d

let (>>) f g x = g ( f(x) )

所以上面的代碼也能夠經過>>來組合:code

let add1ThenMultiply2 x = (>>) add1 multiply2

因爲操做符支持中綴表達式,也即操做符能夠寫在兩個參數的中間,例如+號:blog

(+) 1 3

實際上能夠寫爲:ip

1 + 3

那麼上面的代碼就能夠寫成:class

let add1ThenMultiply2 x = add1 >> multiply2

組合和管道符的區別

上面的例子咱們還能夠用管道符來實現:im

let result1 = 10 |> add1 |> multiply2

管道符和組合的定義看起來很是類似:

let (|>) x f = f x
let (>>) f g x = g ( f(x) )

管道符(|>)接受兩個參數,在往下一個管道符傳遞的時候已經完成了求值,而函數組合實際上生成了新的函數,最後一步傳入實際的參數纔會完成求值。
下面的圖示描述了管道符的求值過程:

相關文章
相關標籤/搜索