为什么不';t型同义词在Haskell中允许递归?
有人能解释一下为什么这两个问题都能顺利解决吗:为什么不';t型同义词在Haskell中允许递归?,haskell,types,Haskell,Types,有人能解释一下为什么这两个问题都能顺利解决吗: data A a b = A { a :: a, b :: b } newtype B a = B (A a (B a)) newtype C = C (A Int C) 但是我不能通过类型同义词创建类似的递归定义的类型 type B a = A a (B a) type C = A Int C 虽然显然databa=a{a::a,B::ba}工作得很好 有没有办法避免在我想要递归类型的任何地方处理额外的构造函数X?我主要是通过访问器函数来选择
data A a b = A { a :: a, b :: b }
newtype B a = B (A a (B a))
newtype C = C (A Int C)
但是我不能通过类型同义词创建类似的递归定义的类型
type B a = A a (B a)
type C = A Int C
虽然显然databa=a{a::a,B::ba}
工作得很好
有没有办法避免在我想要递归类型的任何地方处理额外的构造函数X?我主要是通过访问器函数来选择b
,所以我基本上没问题,但是如果存在一个简单的规避机制,我想知道它
我应该使用哪些pragma来提高专用数据类型C的性能?只是专门做些什么
在
aab
和acd
之间复制有没有聪明的技巧,只定义A->b
和c->d
映射而不复制记录两次?我担心A
的字段将来会改变。也许是哈斯克尔 我会回答你的第一个问题和第二个问题
B的类型是无限类型(A A(A A(A A(…)))))
“类型推断引擎”可以设计为推断和处理无限类型。不幸的是,程序员的许多错误(排版错误或逻辑错误)创建的代码没有达到所需的有限类型,并且意外地具有无限类型。现在编译器拒绝这样的代码,这几乎总是程序员想要的。将其更改为允许无限类型将在编译时造成更难理解的错误(至少与C++模板一样糟糕),并且在极少数情况下,可能会使其编译并在运行时错误地执行。
有没有办法避免处理额外的构造函数X
我想要递归类型的任何地方
否。Haskell已选择只允许递归类型和数据或新类型中的显式类型构造函数。这使得代码更加冗长,但是newtype
应该不会对运行时造成什么损失。这是一个设计决策。这与VS有关。Haskell使用iso递归类型实现递归类型,这要求程序员在发生类型递归时告诉类型检查器。标记它的方式是使用特定的构造函数,而简单的类型同义词不允许使用该构造函数
等递归类型允许编译器推断递归发生的位置,但它会导致更复杂的类型检查器,在某些看似简单的情况下,问题是无法确定的
如果你想好好讨论equi和iso递归类型,可以看看benjaminpierce的优秀文章
简短回答:因为类型同义词不引入构造函数,haskell需要构造函数在类型级别显式标记递归,所以不能使用递归类型同义词。newtype
对GHC没有任何运行时惩罚。我不确定这是否是报告所要求的,但我似乎记得与所要求的包装类型相同的表示形式。啊,是的,如果不小心的话,我想这可能是偶然发生的,但otohB
只是循环链接列表的类型,对于Haskell来说没有什么不寻常的。啊,哎呀,哈斯克尔似乎比我想象的更不喜欢我的唱片了。newtype Foo t=Foo t
并没有运行时惩罚map Foo
是将[t]
转换为[Foo t]
的安全方法。它确实如此,但并不便宜。一个类型检查器应该如何比较无限类型的相等性呢?@trinithis:是的;一般来说,您可以安全地unsafeccerce
消除newtype
与其表示形式之间的任何差异。啊,谢谢您的参考。如果我理解正确,类型的对于所有a
实际上意味着“除了我以外的所有人”。这是必要的,因为程序员必须在递归发生时告诉它。不,对于所有a
的与多态性有关。实际上,创建递归类型不需要类型参数<代码>数据A=A A
非常好。问题是haskell在决定术语的类型时,必须知道在哪里停止“向下钻取”。当它找到构造函数时,它知道在计算整个术语的类型时,它不必深入到该子术语。在数据A=A A A
中没有任何forall
,但是,forall
仅在类型保持未指定时出现,这需要这个newtype
技巧。我以为你在问forall
是否与递归类型有关。没有。我只是说,每当你有任何类型的递归类型时,都需要“newtype技巧”,不管它是否是多态的(有未指定的类型)。我一直想知道为什么Haskell不允许无限类型(它总是允许无限数据)。有“正确”吗无需模式绑定或写入unC(ca)=a
someplace就可以删除构造函数C
的方法?newtype C=C{unC::a Int C}
做你想做的吗?我想这是等效的,只是询问是否有一些标准技巧。如果一个值在GHC中有一个newtype
构造函数,您可以使用unsafeccerce
:)将其删除