这是一个愚蠢的问题,一直在困扰着我。为什么我不能写一个具有多个参数的新类型,多参数newtype伪造一个元组?
newtype A = A Int Int
而元组版本就好了?
newtype A = A (Int, Int)
前者在模式匹配等事情上要好得多。
这是一个愚蠢的问题,一直在困扰着我。为什么我不能写一个具有多个参数的新类型,多参数newtype伪造一个元组?
newtype A = A Int Int
而元组版本就好了?
newtype A = A (Int, Int)
前者在模式匹配等事情上要好得多。
newtype A = A Int
创建一个与Int
同构的类型。就是说,它的行为完全像Int
w.r.t.例如bottom
,但名称不同。
这与data A = A Int
形成鲜明对比,该创建的行为与Int的行为不同。还有另一个值不在Int
:A 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
一些其他的意思是免费的,从这些不一致(否则会被发现和使用,我想;)
因为newtype
,粗略地说,就像type
在运行时如编译时的data
。每个data
定义增加了一个额外的间接层 - 在正常情况下,这意味着另一个不同的地方,其中某些东西可以作为thunk保留 - 围绕其保留的值,而newtype
则不然。 newtype
上的“构造函数”基本上只是一种幻想。
凡是将多个值成一个,或者,让多个案件之间的选择,必须引入了一个间接层来表达,所以newtype A = A Int Int
逻辑解释将是两个断开Int
值与无“它们保持在一起” 。 newtype A = A (Int, Int)
的区别在于元组本身增加了额外的间接层。
将此与data A = A Int Int
与data A = A (Int, Int)
对比。前者在两个Int
周围添加一层(A
构造函数),而后者在元组周围添加相同的图层,该图层本身围绕Int
添加一层。
每一层间接还通常增加一个地方可以⊥,所以考虑每种形式的可能情况下,在哪里?代表非底值:
对于newtype A = A (Int, Int)
:⊥
,(⊥, ?)
,(?, ⊥)
,(?, ?)
对于data A = A Int Int
:⊥
,A ⊥ ?
,A ? ⊥
,A ? ?
对于data A = A (Int, Int)
:⊥
, A ⊥
,A (⊥, ?)
,A (?, ⊥)
,A (?, ?)
从上面可以看出,前两个是等价的。
最后要注意,这里有究竟有多newtype
从data
不同的乐趣演示。考虑这些定义:
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中找出!
你读过[this](http://www.haskell.org/haskellwiki/Newtype)吗? –
@ n.m。,感谢您的链接,但您能否详细说明实际问题?它与匹配'(A _ _)'有关吗?我不明白为什么元组等价会导致不直观的行为。 – gatoatigrado