嵌套参数化类型的实例

时间:2011-09-06 13:24:19

标签: haskell typeclass

鉴于我有数据类型

data A a = A a
data B b = B b

和类型类

class C c where
    f :: c a -> a

现在C类需要一种类型* -> *,所以我可以做

instance C A where
    f (A a) = a

instance C B where
    f (B b) = b

现在给出一个如下函数:

ab :: b -> A (B b)
ab = A . B

如何为结果类型声明C的实例?

我首先通过我可以使用TypeSynonymInstances的类型同义词,如下所示:

type AB b = A (B b)
class C AB where
    f (A (B b)) = b

特别是因为ghci报告了正确的类型:

*Main> :k AB
AB :: * -> *

但是,您似乎无法在实例声明中使用部分应用的类型同义词(或者在任何地方使用)。

我是否可以通过某种方式组合类型AB,就像我可以编写构造函数一样,或者使用其他语法来声明这种嵌套类型的实例?

3 个答案:

答案 0 :(得分:6)

最简单的可能是定义

newtype AB a = AB { unAB :: A (B a) }

GHC应该能够为此派生一个C实例。

您也可以使用TypeCompose来完成此操作,

type AB = A :. B

instance C AB where
  f = f . f . unO

答案 1 :(得分:2)

无法声明此类实例。实际上,在实例声明中允许任意类型的函数(如AB)会使实例解析不可判定。

通常,解决方案是声明一个newtype。当然,当您想要使用该类时,您必须显式转换为newtype。

newtype AB a = AB (A (B a))
instance C AB where f (AB (A (B a)) = a

如果您对该类的使用足够简单,您可能只想将重载方法作为使用它的函数的参数传递。

答案 2 :(得分:1)

您必须使用newtype。必须始终完全应用类型同义词,因为它只是同义词,而不是lambda。 newtype没有运行时惩罚;它将在编译时被删除。