2011-08-07 56 views
9

這是一個愚蠢的問題,一直在困擾着我。爲什麼我不能寫一個具有多個參數的新類型,多參數newtype僞造一個元組?

newtype A = A Int Int 

而元組版本就好了?

newtype A = A (Int, Int) 

前者在模式匹配等事情上要好得多。

+2

你讀過[this](http://www.haskell.org/haskellwiki/Newtype)嗎? –

+0

@ n.m。,感謝您的鏈接,但您能否詳細說明實際問題?它與匹配'(A _ _)'有關嗎?我不明白爲什麼元組等價會導致不直觀的行爲。 – gatoatigrado

回答

10

newtype A = A Int創建一個與Int同構的類型。就是說,它的行爲完全像Int w.r.t.例如bottom,但名稱不同。

這與data A = A Int形成鮮明對比,該創建的行爲與Int的行爲不同。還有另一個值不在IntA undefined(與undefined::A不同)。

現在,newtype A = A (Int, Int)創建一個與(Int, Int)同構的類型。順便說一句,這正是data A = A Int Int所做的。

所以,如果我們承認newtype A = A Int Int等同於newtype A = A (Int, Int),我們有什麼? newtype A = A Int Int相當於newtype A = A (Int, Int),相當於data A = A Int Int

newtype A = A Int Int相當於data A = A Int Int(所以newtype是在這種情況下冗餘),

newtype A = A Int相當於data A = A Int(這是在第一位置具有newtype整點)。

所以我們必須得出結論newtype A = A Int Int相當於newtype A = A (Int, Int)會造成冗餘和不一致,我們最好不允許它。

有可能沒有辦法給newtype A = A Int Int一些其他的意思是免費的,從這些不一致(否則會被發現和使用,我想;)

7

因爲newtype,粗略地說,就像type在運行時如編譯時的data。每個data定義增加了一個額外的間接層 - 在正常情況下,這意味着另一個不同的地方,其中某些東西可以作爲thunk保留 - 圍繞其保留的值,而newtype則不然。 newtype上的「構造函數」基本上只是一種幻想。

凡是將多個值成一個,或者,讓多個案件之間的選擇,必須引入了一個間接層來表達,所以newtype A = A Int Int邏輯解釋將是兩個斷開Int值與無「它們保持在一起」 。 newtype A = A (Int, Int)的區別在於元組本身增加了額外的間接層。

將此與data A = A Int Intdata A = A (Int, Int)對比。前者在兩個Int周圍添加一層(A構造函數),而後者在元組周圍添加相同的圖層,該圖層本身圍繞Int添加一層。

每一層間接還通常增加一個地方可以⊥,所以考慮每種形式的可能情況下,在哪裏?代表非底值:

  • 對於newtype A = A (Int, Int)(⊥, ?)(?, ⊥)(?, ?)

  • 對於data A = A Int IntA ⊥ ?A ? ⊥A ? ?

  • 對於data A = A (Int, Int)A ⊥A (⊥, ?)A (?, ⊥),A (?, ?)

從上面可以看出,前兩個是等價的。


最後要注意,這裏有究竟有多newtypedata不同的樂趣演示。考慮這些定義:

data D = D D deriving Show 
newtype N = N N deriving Show 

什麼可能的值,包括所有可能的⊥s,這些都有嗎?你認爲以下兩個值是什麼?

d = let (D x) = undefined in show x 
n = let (N x) = undefined in show x 

將它們加載到GHC中找出!