4

我的代码中有类似于此类的内容。在我的情况下,将 a' 作为另一个参数添加到类 Foo 是没有意义的。

class Foo a where
    type FCtx a a' :: Constraint
    type FCtx a a' = ()

    f :: (FCtx a a') => a -> a'

data D b = D b

instance (Integral b) => Foo (D b) where
    -- the next line does not compile because b' does not appear on the LHS
    type FCtx (D b) a' = (a' ~ D b', Integral b') 

    f (D x) = D $ fromIntegral x

对于这个特定的实例Foo,我想a'以这种方式关联。我想出完成这项工作的唯一方法是添加一个具有“明显”类型同义词的“虚拟”类:

class DClass d where
   type DType d

instance DClass (D b) where
    type DType (D b) = b

实例现在Foo变为:

instance (Integral b) => Foo (D b) where
    type FCtx (D b) a' = (a' ~ D (DType a'), Integral (DType a'))
    f (D x) = D $ fromIntegral x

问题是我必须为我的特定数据类型创建一个完整的类(和实例),只是为了表达(D b)确定 b 的类型同义词/功能依赖性。我不会有这个类的任何其他实例,因为我总是DType a'将类型参数表示为D b.

我想做的是:

type DParam (D b) = b

instance (Integral b) => Foo (D b) where
     type FCtx (D b) a' = (a' ~ D (DParam a'), Integral (DParam a'))
     f (D x) = D $ fromIntegral x

或者甚至可以在完全不使用类型同义词的情况下用更好的方式来表达这个约束。似乎很愚蠢,我应该被迫创建一个具有单个实例的类型同义词的(开放)类来实现这一点,并且其他人可能会创建我不打算创建的新实例是不安全的。

至少,不会有一些规范的方式将“模式匹配类型同义词”转换为DClass上面的类/实例吗?

4

1 回答 1

5

重量稍轻,使用类型族:

type family DParam d :: *
type instance DParam (D b) = b

不知道你现在能不能做得更好……

于 2013-01-24T07:53:32.920 回答