2012-04-20 87 views
13

我是Haskell的新手,目前正在通過Real World Haskell。本書說類型構造函數僅用於類型簽名,而值構造函數用於實際代碼中。它也給出了一個聲明的例子,表明兩者的名稱是相互獨立的。爲什麼首先需要兩個構造函數,如果其中只有一個用於實際代碼?由於我們不會在實際代碼中使用類型構造函數,因此類型構造函數的用途是什麼?爲什麼除了Haskell中的類型構造函數外,還有一個值構造函數?

+11

短語「實際代碼」是不幸的,因爲它暗示你不會在程序中使用類型構造函數,而作者實際上是指類型構造函數僅用於類型註釋。這相當於說你在C中不需要關鍵字「int」或「long」,因爲你在實際代碼中不使用它們(它們只用於聲明中,它不被視爲「實際代碼「按此標準)。 – 2012-04-20 10:24:30

+0

...不接受? :) – 2012-11-27 14:26:32

回答

22

也許名字有​​點誤導。 A 類型構造函數表示您聲明的類型的名稱。它們就是這樣調用的,因爲它們構建的是類型,而不是值:實際上,(可能)對類型變量進行參數化,它們定義了一系列類型。它們的行爲類似於C++的模板和Java的泛型。在data MyType a b = Constr a b中,MyType是一個類型構造函數,它需要兩種類型ab來構建一個新類型(MyType a b)

A 值構造函數是您在其他(面向對象)語言中稱爲「構造函數」的唯一部分,因爲您需要它來構建該類型的值。因此,在前面的示例中,如果採用值構造函數Constr :: a -> b -> MyType a b,則可以創建值Constr "abc" 'd' :: MyType [Char] Char

+2

請問如何改進我的答案擺脫那-1?怎麼了? – 2012-04-20 13:42:09

7

一種方便的方式來獲取有關類型和值的直覺是,前者是編譯時值,而後者則是運行時值。換句話說,Type構造函數是Haskell類型集合中值的構造方法,唯一目的是在編譯時鍵入您的程序。這也意味着你不能在運行時構造一個類型,並且你不能在編譯時構造一個值。所以,因爲你不能在運行時根據類型值顯式地分支(儘管你可以隱式地使用類型類型),所以類型構造函數作爲運行時對象是完全沒用的,並且在很多情況下完全沒有最終的二進制。相反,因爲值構造函數允許在運行時在它們的類型集合中構造值,所以它們作爲編譯時對象完全沒有用處。

由於這個簡單的屬性,Type構造函數和Value構造函數可以毫不含糊地共享名稱。

+0

這是對來自緊急背景的人的最簡單理解! – 2013-06-17 13:36:52

16

這有點像說「爲什麼我們需要類對象,如果對象是唯一實際運行?」

這兩種構造函數做不同的工作。類型構造函數進入類型簽名。值構造函數進入可運行代碼。

在最簡單的情況下,類型「構造函數」只是一個類型名稱。在最簡單的情況下,一個類型只有一個值構造函數。所以,你的東西落得像

data Point = Point Int Int

你可以對自己說:「現在爲什麼赫克我需要寫Point兩次?」

但現在考慮不那麼簡單的例子:

data Tree x = Leaf x | Branch (Tree x) (Tree x)

這裏Tree是一個類型構造。你給它一個類型參數,它「構造」一個​​類型。因此Tree Int是一種類型,Tree String是另一種類型,依此類推。 (類似於C++中的模板,或Java或Eiffel中的泛型)。

另一方面,Leaf是一個值構造函數。給定一個值後,它會生成一個單節點樹。所以Leaf 5是一個Tree Int值,Leaf "banana"是一個Tree String值,依此類推。

類似地對於Branch。它需要兩個樹值並構建一個樹狀節點,並將這些樹作爲子節點。例如,Branch (Leaf 2) (Leaf 7)Tree Int的值。

+0

感謝您的詳細解釋! – 2012-04-23 06:28:13

相關問題