簡體   English   中英

Haskell是否支持部分應用函數的組合?

[英]Does Haskell support composition of partially applied functions?

例如,我做不到

f = ((*2).(+)) 3

這是好的,因為我可以隨時做

f = (*2).(+3)

但是當我想創建一個函數列表時,這有點不方便,例如

map ((*2).(+)) [1, 2, 3]

map (+) [1, 2, 3]

沒關系。

當然,我總是可以使用lambda表示法來實現currying:

map (\x y -> 2*(x + y)) [1, 2, 3]

據我所知,GHC不喜歡編寫部分應用的函數,因為它不知道如何將函數類型提供給像(* 2)這樣的操作。

(+) 2 :: Num a => a -> a 
(*2) :: Num a => a -> a 

但我一直認為它應該是一個相當自然的東西:(+)的輸出類型是Num a => a,所以(* 2)應該能夠“吃掉”那個。

我的問題是:這是以某種方式實施的嗎? 或者,是否有人知道為什么在Haskell中沒有實現這么簡單的事情?

Haskell支持部分函數的組合,但是你有類型不匹配。 組成是功能

(.) :: (b -> c) -> (a -> b) -> a -> c

在你的情況下,你有兩個功能

(*2) :: Num a => a -> a
(+)  :: Num a => a -> a -> a

當你編寫這個函數類型的結果時

((*2).(+)) :: (Num (a -> a), Num a) => a -> a -> a

那不是你想要的。 您可以重寫函數f例如(.) (*2) . (+) (.) (*2) . (+)但我認為lambda更具可讀性。

而你混淆了部分功能和部分應用。 部分函數是不為整個域定義的函數,部分應用程序是將多個參數固定到函數的過程,產生較小的arity函數。

如果要點免費,可能會讓人感到困惑。 如果我們通過類型簽名;

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

(+)Num a => a -> a -> a

(2*)Num a => a -> a

現在,如果我們做(2*) . (+) (2*) . (+)(.)的第二個參數,它是(+) ,必須有一個類型(a -> b) ,當我們將(+) s類型重寫為Num a => a -> (a -> a)時,它實際上是真的Num a => a -> (a -> a) 所以我們的b類型恰好是Num a => a -> a 現在記住(.)(b -> c)作為第一個參數。 我們這里有一點問題,因為在我們的表達式中(2*) . (+) (2*) . (+) (2*)等待一個b類型像Num a => a而我們有b型像Num a => a -> a 你不能將函數乘以2 ..! 我們必須將(2*)轉換為這樣一個函數,該函數將采用我們的類型函數,即Num a => a -> a ,運行它並將其結果提供給(2*) 不需要看這不過是(.) 在這種情況下,如果我們再次像((2*) . )那樣寫,我們可以安全地輸入我們的Num a => a -> a類型函數(記住這是部分應用的(+) )。 讓我們把它包起來......

我們的點等效於\\xy -> 2*(x + y)((2*) . ) . (+) ((2*) . ) . (+)

Prelude> (((2*) . ) . (+)) 3 5
16

我們可以使用((->) r)類型的應用函子在這些情況下更容易表達自己。 一旦我有更多時間,我會嘗試添加它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM