我剛開始學習Haskell,對我來說奇怪的事情之一是具有多個參數的函數類型的語法。爲什麼Haskell使用箭頭作爲函數的類型?
舉一個簡單的例子:
(+) :: Num a => a -> a -> a
爲什麼我們需要在這裏所有的箭頭?寫下類似Num Num Num -> Num
的東西不是更有意義嗎?
引擎蓋下的原因是什麼?我搜索了這個問題,但找不到任何真正有用的東西。
我剛開始學習Haskell,對我來說奇怪的事情之一是具有多個參數的函數類型的語法。爲什麼Haskell使用箭頭作爲函數的類型?
舉一個簡單的例子:
(+) :: Num a => a -> a -> a
爲什麼我們需要在這裏所有的箭頭?寫下類似Num Num Num -> Num
的東西不是更有意義嗎?
引擎蓋下的原因是什麼?我搜索了這個問題,但找不到任何真正有用的東西。
令人困惑的第一件事是Num a =>
,所以我們現在完全忽略它。相反,讓我們考慮Int -> Int -> Int
,這是您給出的類型簽名的一種可能的專業化。
Haskell中的函數幾乎總是curried。這意味着多參數函數實際上是一個參數的函數,它返回一個接受下一個參數的函數,依此類推。
->
是正確的聯想,所以Int -> Int -> Int
是與Int -> (Int -> Int)
相同的東西。
這也意味着,這個定義
f :: Int -> Int -> Int
f x y = x + y
相同
f :: Int -> Int -> Int
f x = \y -> x + y
事實上,在Haskell所有函數都只有一個參數。元組也存在,但它們是一流的公民,所以它們不僅僅是一個參數列表。
Num a =>
是類型系統的一個不同方面。它表示類型變量a
必須是Num
類型類的一個實例。作爲Num
的實例的類型的常見示例包括Int
和Double
。所以Num
本身不是一個類型,它是一個類型類。 Num a =>
表示對類型變量a
的約束,它不是該函數的另一個參數。
的(+)
方法是Num
型類的成員,所以你必須要使用(+)
以這種方式約束a
。如果你試圖給f
簽字a -> a -> a
(沒有限制),它將不起作用,因爲a
是完全無約束的,我們對它可以是什麼類型一無所知。因此,我們無法在其上使用(+)
。
+1鏈接! – CSnerd
函數的類型簽名中的每個參數的類型都可以包含空格,因此非空白分隔符很可能是必需的,因此編譯器(和人類!)可以區分它們。
例如,可以有一個參數化的抽象數據類型:
data MyType a = MyValue a
而這需要具體的類型的函數(從MyType
類型構造構造):
myFunc :: MyType Int -> MyType Int -> String
如果沒」 t之間有參數->
,簽名看起來像
myFunc :: MyType Int MyType Int -> String -- Not valid code
和一個編譯器在計算函數的實際參數意味着什麼時會遇到更多麻煩(我想知道在某些情況下甚至可能不可能?)。至少,這是不太容易理解的。
我懷疑你已經理解了這個問題。他問爲什麼Haskell使用'A - > B - > C'而不是'A B - > C'。即:' - >'左邊是參數列表,右邊是返回類型。 – Shoe
@傑弗裏你說得對,我錯過了。我已經稍微編輯了我的答案。 –
如果你有'(Ord a,Num a)=> a - > a - > a',你會寫些什麼? – Squidly