这是一个愚蠢的问题,已经困扰了我一段时间。为什么我不能写一个带有多个参数的新类型,
newtype A = A Int Int而元组版本就没问题了?
newtype A = A (Int, Int)前者在模式匹配等方面要好得多。
发布于 2011-08-07 13:40:57
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),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其他含义,使其不受这些不一致的影响(否则,我想它会被发现并使用;)
发布于 2011-08-07 13:47:54
因为粗略地说,newtype在运行时类似于type,而在编译时类似于data。每个data定义都在它持有的值周围增加了一层额外的间接层--在正常情况下,这意味着可以将一些东西留在另一个不同的地方--而newtype不是这样。newtype上的“构造函数”基本上只是一种错觉。
任何将多个值组合成一个值,或者在多个情况之间提供选择的任何东西,都必然会引入一层间接层来表达这一点,因此newtype A = A Int Int的逻辑解释应该是两个不相连的Int值,没有任何东西“将它们保持在一起”。newtype A = A (Int, Int)的不同之处在于,元组本身添加了额外的间接层。
将这与data A = A Int Int和data A = A (Int, Int)进行对比。前者在两个元组周围添加一个层( A构造函数),而后者在元组周围添加相同的层,后者本身在Int周围添加一个层。
每一层的间接层通常也会添加一个地方,在那里某些东西可以是⊥的,所以考虑一下每种形式的可能情况,在哪里?表示非底部的值:
(?, ?)
newtype A = A (Int, Int):⊥,(⊥, ?),(?, ⊥),A (?, ?)
⊥,A ⊥ ?,D26,A ? ?
A (?, ?)
,⊥,A ⊥ ?,D34
从上面可以看出,前两个是等价的。
最后,这里有一个有趣的演示来说明newtype与data的不同之处。考虑以下定义:
data D = D D deriving Show
newtype N = N N deriving Show包括所有可能的⊥,每一个都有什么可能的值?你认为下面的两个值是什么?
d = let (D x) = undefined in show x
n = let (N x) = undefined in show x将它们加载到GHC中并找出答案!
https://stackoverflow.com/questions/6970662
复制相似问题