Haskell TypeCast类型

时间:2013-11-22 04:05:00

标签: haskell type-level-computation

我在Haskell的几个不同的地方遇到了一个名为TypeCast的类型类。

这是相当神秘的,我似乎无法完全解析它。

class TypeCast   a b   | a -> b, b -> a     where typeCast   :: a -> b
class TypeCast'  t a b | t a -> b, t b -> a where typeCast'  :: t -> a -> b
class TypeCast'' t a b | t a -> b, t b -> a where typeCast'' :: t -> a -> b

instance TypeCast' () a b => TypeCast a b where typeCast x = typeCast' () x
instance TypeCast'' t a b => TypeCast' t a b where typeCast' = typeCast''
instance TypeCast'' () a a where typeCast'' _ x = x

http://okmij.org/ftp/Haskell/typecast.html对此代码提供了有用但却敷衍的评论。有关详细信息,该页面指向http://homepages.cwi.nl/~ralf/HList/paper.pdf,这是一个断开的链接。

我看到TypeCast是一个允许您从一种类型转换为另一种类型的类,但我不明白为什么我们需要TypeCast'TypeCast''

看起来所有这些代码都允许您将类型转换为自身。在我看过的一些示例代码中,我尝试将其替换为:

class TypeCast a b | a -> b, b -> a where typeCast :: a -> b
instance TypeCast a a where typeCast a = a

并且样品仍然有效。我一直在看的样本主要来自第一个链接。

我想知道是否有人可以解释六条线的用途。

2 个答案:

答案 0 :(得分:5)

TypeCast实际上是什么用?

它不用于检索有关存在类型的类型信息(这会破坏类型系统,因此不可能)。要理解TypeCast,我们首先要了解有关haskell类型系统的一些特定细节。考虑以下激励示例:

data TTrue
data TFalse

class TypeEq a b c | a b -> c

instance TypeEq x x TTrue
instance TypeEq x y TFalse 

这里的目标是在类型级别上有一个布尔标志 - 它告诉你两个类型是否相等。您可以使用~来表示类型等价 - 但这只会使您在类型上失败(即Int ~ Bool不编译而不是TypeEq Int Bool rr ~ TFalse作为推断类型)。但是,这不会编译 - 功能依赖性冲突。原因很简单 - x x只是x y的实例化(即x ~ y => x y == x x),因此根据fundeps的规则(请参阅完整的文档)规则的细节),这两个实例必须具有c的相同值(或者这两个值必须是彼此的实例 - 它们不是)。

TypeEq库中存在HList类 - 让我们来看看它是如何实现的:

class HBool b => TypeEq x y b | x y -> b
instance TypeEq x x HTrue
instance (HBool b, TypeCast HFalse b) => TypeEq x y b
-- instance TypeEq x y HFalse -- would violate functional dependency

当然这些实例不会发生冲突 - HTrue b的实例化。可是等等! TypeCast HFalse b是否b 必须 HFalse?是的,确实如此,但编译器在尝试解决fundep冲突时没有检查类实例约束。这是允许此类存在的关键“功能”。 简要说明 - 两个实例仍然重叠。但是对于-XUndecidableInstances -XOverlappingInstances,编译器将首先选择第一个实例 ,因为第一个实例更具“特异性”(在这种情况下,这意味着它最多只有2个唯一)类型 - xHTrue,而另一个实例最多有3个)。您可以找到UndecidableInstances在文档中使用的完整规则集。

为什么TypeCast按原样编写?

如果你查看HList的源代码,有TypeCast的多个实现。一个实现是:

instance TypeCast x x

一个人认为可行的直截了当的实例。不!从包含上述定义的文件中的注释:

   A generic implementation of type cast. For this implementation to
   work, we need to import it at a higher level in the module hierarchy
   than all clients of the class. Otherwise, type simplification will
   inline TypeCast x y, which implies compile-time unification of x and y.

也就是说,类型简化器(其作用是删除类型同义词和常量类约束的使用)将在x ~ y中看到TypeCast x x,因为这是唯一匹配的实例,但仅在某些情况下。由于在不同情况下行为不同的代码是“非常糟糕”,因此HList的作者有第二个实现,即原始帖子中的实现。让我们来看看:

class TypeCast     a b |   a -> b,   b -> a   
class TypeCast'  t a b | t a -> b, t b -> a 
class TypeCast'' t a b | t a -> b, t b -> a 

instance TypeCast'  () a b => TypeCast    a b 
instance TypeCast''  t a b => TypeCast' t a b 
instance TypeCast'' () a a 

在这种情况下,TypeCast x y可以从不简化而不查看类约束(简化器不会这样做!);没有实例头,这可能意味着x ~ y

但是,我们仍然需要在某个时间点断言x ~ y - 所以我们用更多的类来做! 我们在a ~ b中了解TypeCast a b的唯一方法是TypeCast () a b隐含a ~ b。仅当TypeCast'' () a b暗示a ~ b时才会出现这种情况。

我不能不讲你的全部故事;我不知道为什么

instance TypeCast' () a b => TypeCast a b 
instance TypeCast' () a a

不够(它有效 - 我不知道为什么它不会被使用)。我怀疑它与错误消息有关。我相信你可以找到Oleg并问他!

答案 1 :(得分:2)

HList文件发表在2004年Haskell研讨会的会议记录中,因此可从ACM DL和其他档案中获取。唉,发布版本中的解释缩写为缺乏空间。有关完整说明,请参阅作为技术报告发布的论文的扩展版本,该报告可在以下网址获得 http://okmij.org/ftp/Haskell/HList-ext.pdf(自从Ralf很久以前离开CWI以来,CWI链接确实不再有效。)请参阅TR中的附录D以解释TypeCast。

在最新的GHC中,您可以编写TypeCast x y而不是x ~ y约束。没有相应的typeCast方法:不再需要它。当您编写x ~ y约束时,GHC会自动和幕后合成类似于类型广播(称为强制)的内容。

直接在电子邮件中询问我的问题通常可以更快地回复。