2013-02-11 75 views
6

在读编译运行管道的各个阶段,type声明和newtype声明之间有什么不同?类型和新类型之间的编译时间和运行时间差

我的假设是,他们编译成相同的机器指令,而唯一的区别是,当程序typechecked,其中,例如

type Name = String 
newtype Name_ = N String 

您可以使用一个Name任何地方String是必需的,但是如果您使用Name_(其中String是预期的,即使它们编码了相同的信息),类型检测器也会将您叫出来。

我问这个问题,因为如果是这样的话,我看不出有任何理由如下声明不应该是有效的:

type List a = Either() (a, List a) 
newtype List_ a = L (Either() (a, List_ a)) 

然而,类型检查器接受第二一但拒绝第一个。这是为什么?

+10

这不是一个编译问题,它是一个类型检查问题。 Haskell使用“iso-recursive types”而不是“equi-recursive types”,所以如果你希望你的类型是递归的,你必须在那里有一个'data'或'newtype'。每种选择都有各种各样的权衡。请参阅Pierce的类型和编程语言以了解更多关于这些系统和涉及的选择。 – luqui 2013-02-11 12:03:52

+2

谢谢,我想我只需要“iso-recursive”和“equi-recursive”这两个名字就可以知道Google要做什么!如果你想将其转换为答案,我会接受它。 – 2013-02-11 12:08:11

回答

4

Luqui的评论应该是一个答案。 Haskell中的类型同义词首先近似于宏。也就是说,它们被类型检查器扩展为完全评估的类型。类型检查器不能处理无限类型,所以Haskell不具有等递归类型。

newtypes为您提供的iso-recursive类型,在GHC中,本质上是编译为核心语言中的等递归类型。 Haskell不是GHC核心,所以你不能访问这些类型。 Equi递归类型对于类型检查器和人类都有点难,而iso-recursive类型具有相同的功能。

+0

感谢Philip。我是否理解GHC Core具有等递归类型? “newtype”标签中的信息在什么阶段消失? – 2013-02-11 19:48:34

+0

我避免了像瘟疫一样的核心,所以把我说的一切都说出来:GHC核心有iso-recursive类型。核心中不存在新类型。我的看法是,这可能会被未来使用类型等式约束所取代:所以'List_a =(或者()(a,r))〜r => r',并在每个用例中插入这些等式的证明(做这件事的机器已经存在)。 – 2013-02-11 19:55:31

+0

@PhilipJF:[这有点复杂](http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/FC#Newtypesarecoercedtypes)现在,newtypes可以编译成数据类型和类型等式公理:'newtype T = MkT Int'产生axT:T〜Int'的公理。不幸的是,这是不健全的:如果我们有'键入家族F a;类型实例F Int = Bool;类型实例F T = Char',然后是'Bool_F Int','F Int_F T'和'F T_Char'。因此'Bool〜Char',我们遇到了麻烦。 [这实际上可以用'GeneralizedNewtypeDeriving'。](http://hackage.haskell.org/trac/ghc/ticket/1496) – 2013-02-12 06:08:02