我想编写一个可以在各种同构格式之间转换类型的库,从“子类型”转换为“超类型”,例如使用以下同构和注入:
(a, (b, c))
<〜> ((a, b), c)
(Either a (Either b c))
<〜> (Either (Either a b) c)
(a, ())
<〜> a
<〜> ((), a)
(Either a Void)
<〜> a
<〜> (Either Void a)
(a, Void)
<〜> Void
<〜> (Void, a)
((a, b) -> c)
<〜> a -> (b -> c)
(() -> c)
<〜> ç
(a, Either x y)
<〜> Either (a, x) (a, y)
(Either x y, a)
<〜> Either (x, a) (y, a)
a
〜> x -> a
(常数函数)
Int
〜> Integer
Int
〜> Double
a
〜> ()
......以及它的嵌套组合。
它的工作原理(通过将输入类型转换为规范的同构形式,深入应用子类型注入而非去规范化到结果类型),但主要仅用于单型。在只能通过构造函数(->)
,Either
和(,)
的类型构造函数的树中可到达的位置使用多态类型将导致“模糊类型”错误消息,因为确定应用哪些转换的重叠类型类无法解析,这很好,因为类型变量可能可能被实例化为例如对类型,并且忽略这将使整个转换不相干。
如何将Type变量既不是(a -> b)
形式,也不是(a, b)
形式,也不是(Either a b)
形式?我试过这个:
class BinaryTC tc x (r::Bool) a b | tc x a b -> r
instance {-# OVERLAPPING #-} (r~'False) => BinaryTC tc (tc a b) r a b
instance {-# OVERLAPPABLE #-} (r~'True) => BinaryTC tc x r a b
type NotHaskGenerating x = (
ForallV (BinaryTC (,) x 'False),
ForallV (BinaryTC (->) x 'False),
ForallV (BinaryTC Either x 'False)
)
为了约束多态类型变量,但它不起作用,甚至在规范化阶段也是如此。这是因为ForallV
约束中包含的信息显然只能通过instV
函数实例化,而且必须在表达式级别手动完成。有没有办法教GHC自动使用Forall
约束的信息?另一种方法是将每个值包装在Identity
仿函数中,但我希望能够对变量设置约束。