我的代码中有类似于此类的内容。我的情况是将'作为另一个参数添加到类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
?
答案 0 :(得分:5)
重量稍轻,使用类型系列:
type family DParam d :: *
type instance DParam (D b) = b
不确定你现在能不能做得更好......