[英]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.