類型類是泛化函數的一種方式,以便它們可以是多態的,而其他類型可以爲它們自己的類型實現這些函數。以一個例子的類型類Show
,它以簡化的形式看起來像
class Show a where
show :: a -> String
這表示實現該Show
類型類的任何類型的可以被轉換爲一個String
(有用於更逼真的約束一些更復雜,但具有Show
的點就是能夠將值轉換爲String
s)。
在這種情況下,函數show
具有完整類型Show a => a -> String
。
如果我們檢查功能sqrt
,它的類型是
> :type sqrt
sqrt :: Floating a => a -> a
而對於abs
:
> :type abs
abs :: Num b => b -> b
如果你問GHCI的類型是什麼它會在兩種情況下使用類型變量a
,但我在abs
的類型簽名中使用了b
來明確這些是同名的不同類型變量,這有助於避免在下一步中出現混淆。
這些類型簽名意味着sqrt
需要一個值,其類型實現了Floating
類型類(使用:info Floating
看到所有的成員),並返回相同類型的值,並且該abs
函數採用其類型實現了Num
值typeclass並返回相同類型的值。
表達式abs(show)
等效解析爲abs sqrt
,這意味着sqrt
是傳遞給abs
的第一個也是唯一的參數。但是,我們只是說abs
取值爲Num
類型,但sqrt
是一個函數,而不是數字。爲什麼Haskell接受這個而不是抱怨?當我們使用類型簽名進行替換時,可以更清楚地看到原因。由於sqrt
的類型是Floating a => a -> a
,這必須與abs
的類型簽名中的參數b
相匹配,所以通過將b
替換爲Floating a => a -> a
,我們得到abs sqrt :: (Floating a, Num (a -> a)) => a -> a
。
Haskell實際上允許函數類型實現類型類型Num
,你可以自己做,雖然它可能是荒謬的。然而,僅僅因爲某些東西似乎對GHC沒有意義,只要類型可以乾淨地解決,它就可以實現。
你不能真的使用這個功能,它只是沒有意義。對於任何a
,沒有內置的Num (a -> a)
實例,因此您必須定義自己的實例。你可以,但是,組成使用複合算.
功能abs
和sqrt
:
> :type abs . sqrt
abs . sqrt :: Floating c => c -> c
這有一定道理。此功能相當於這裏
myfunc x = abs (sqrt x)
注意x
首次應用於sqrt
,然後將該計算的結果傳遞給abs
,而不是sqrt
傳遞函數abs
。
我投票結束這個問題作爲題外話,因爲它似乎你從來沒有打擾到檢查出基本介紹哈斯克爾。我真誠地想知道是什麼讓你認爲'abs(sqrt)'會起作用,什麼使你使用這種語法。 –
@OtosakaYuu:它是'abs sqrt'而不是'abs(sqrt)' - 後者會誤導你和其他人; ((+1)(1))「相同,它實際上就是」((+)1)「(在'1'周圍沒有parens),並且運算符部分簡化爲」(1 +)「 。瞭解並遵守這些規則將導致對Haskell的更好理解,以及清晰,慣用,專業外觀的代碼。 –