2011-08-07 68 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中找出!