[英]Why does Haskell use arrows for the type of a function?
我剛剛開始學習Haskell,其中一個奇怪的事情是具有多個參數的函數類型的語法。
考慮一個簡單的例子:
(+) :: Num a => a -> a -> a
為什么我們需要這里的所有箭頭? 寫Num Num Num -> Num
會不會更有意義?
引擎蓋下的原因是什么? 我搜索了這個問題,但找不到任何有用的東西。
令人困惑的第一件事是Num a =>
,所以我們現在將完全忽略它。 相反,我們考慮Int -> Int -> Int
,這是您給出的類型簽名的一種可能的特化。
功能幾乎都是柯里在Haskell。 這意味着多參數函數實際上是一個參數的函數,它返回一個接受下一個參數的函數,依此類推。
->
是右關聯的,因此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
完全不受約束,我們對它可以是什么類型一無所知。 結果,我們無法使用(+)
。
函數類型簽名中每個參數的類型可以包含空格,因此非常需要非空白分隔符,因此編譯器(和人類!)可以區分它們。
例如,您可以擁有參數化的抽象數據類型:
data MyType a = MyValue a
和一個采用具體類型的函數(從MyType
類型構造函數構造):
myFunc :: MyType Int -> MyType Int -> String
如果參數之間沒有->
,則簽名看起來像
myFunc :: MyType Int MyType Int -> String -- Not valid code
並且編譯器在計算函數的實際參數意圖時會遇到更多麻煩(我想知道在某些情況下它甚至可能是不可能的嗎?)。 至少,它更不容易理解。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.