2010-06-28 72 views
6

在Haskell,你爲什麼會定義一個類型約束功能:試圖瞭解Haskell的=> VS定義類型

ghci> :t (==) 
(==) :: (Eq a) => a -> a -> Bool 

而不是定義它,所以它的類型是:

ghci> :t (==) 
(==) :: Eq -> Eq -> Bool 
+0

hese兩個語句不相等 – 2010-06-28 21:11:33

回答

8

你不會做第二個版本,因爲你會得到一個編譯錯誤。 Eq不是一個類型,它是一個類型類型。你不能在需要類型的地方使用類型類。

如果你沒有定義自己的類型MyEq,然後定義一個函數==與類型MyEq -> MyEq -> Bool,表達"hello" == "hello"會因爲"hello"是一個String類型的值,而不是類型MyEq的是無效的。由於haskell中沒有子類型,因此值不能同時爲String類型和MyEq類型。

所以,如果你想定義,它可以接受不同類型的符合一定條件的值的功能,你需要類型類。

+0

要跟上這一點,請參閱運行'let a :: Eq - > Eq - > Bool得到的錯誤; a b c = b == c;在ghci的2 2'中。 – 2010-06-28 21:13:39

+0

謝謝你們,這會讓事情變得直白! – sneeu 2010-06-28 21:26:18

7

在Haskell中,「類型」只能有一組特定的可能值 ,它們不會與任何其他類型重疊。 沒有一種類型是「另一種」 或「另一種類型的子類型」。

當我們需要多態性時,即可以應用於多於一個類型的函數時,我們可以指定通過使用函數的 類型的類型變量。

但是一個類型變量可以參考任何 類型。我們並不總是知道如何爲絕對每種類型定義我們的功能 。例如,(>) 函數僅適用於元素類型爲 的類型。編譯器將拒絕 函數,其類型簽名過於籠統,爲了幫助我們避免編寫亂碼,請按 排序。

在你的榜樣,Eq不是一個類型。它是一個 類型類 - 一組類型的名稱。我們聲明使用class關鍵字 類型類的名稱,並添加 類型轉換成使用instance 關鍵字的類。類型類型的目的是用於約束 限制類型變量的作用域。

Haskell的方法類型和多態性是基於 「辛德米爾納型系統」上。它是描述數據,使得它更容易 給編譯器一個巨大的智力 的金額約在你的程序的類型極其精確 又極富表現力的方式。智力幫助 編譯器自動推斷類型,給你 一個很大的幫助讓你的程序是正確的,並優化 編譯的結果,還有其他好處。

但要小心 - 它與OOP中使用的類型是 的方式非常不同,這可能是您習慣的方式。OO程序和Haskell程序之間通常不存在直接翻譯。 你必須以不同的方式從 開始考慮任務。特別注意不要將「class」和「instance」的Haskell概念 與在OOP中使用這些 單詞的方式完全不同。

+0

「它與OOP中使用的類型非常不同」,我不同意。 Haskell類型類真的很像OOP中的「抽象類」或「接口」,我懷疑有些vtable會隨着參數傳遞給運行時調度發生的多態函數。 – 2010-06-30 08:38:40