Haskell类型转换类型类

Haskell类型转换类型类,haskell,type-level-computation,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

我在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
对此代码给出了一个有用但敷衍的注释。要了解更多信息,该页面会指向断开的链接

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

看起来这段代码所做的只是允许您将类型强制转换为自身。在我看到的一些示例代码中,我尝试将其替换为:

class TypeCast a b | a -> b, b -> a where typeCast :: a -> b
instance TypeCast a a where typeCast a = a
而且样本仍然有效。我一直在看的样本大多来自第一个链接


我想知道是否有人能解释这六行是用来做什么的。

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 r
r~TFalse
作为推断类型)。但是,这不会编译-函数依赖项冲突。原因很简单-
xx
只是
xy
的一个实例(即
x~y
=>
xy==xx
),因此根据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冲突时不检查类实例约束。这是关键的“专长”“ure”,它允许此类存在。 简单地说,这两个实例仍然是重叠的。但是对于
-xundecidableincess-XOverlappingInstances
,编译器会优先选择第一个实例,因为第一个实例更“特定”(在本例中,这意味着它最多有2个唯一类型-
x
HTrue
,而另一个实例最多有3个)。您可以在文档中找到
不可判定实例
使用的全套规则

为什么排版是这样写的?

如果您在源代码中查找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.
也就是说,类型简化器(其工作是删除类型同义词和常量类约束的使用)将在
TypeCast x
中看到
x~y
,因为这是唯一匹配的实例,但仅在某些情况下匹配。由于在不同情况下表现不同的代码“非常糟糕”,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
,因此我们使用更多的类来实现这一点! 在
TypeCast a b
中,我们能知道
a~b
的唯一方法是如果
TypeCast()a b
意味着
a~b
。只有
TypeCast''()a b
意味着
a~b
,情况才是这样

不幸的是,我不能告诉你整个故事,我不知道为什么

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

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

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
不编译,而
typeq Int Bool r
r~TFalse
作为推断类型)。但是,这不会编译-函数依赖项冲突。原因很简单-
x
只是
xy
的一个实例(即
x~y
=>
xy==xx
),因此根据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
?是的,我