类型同义词中的模式匹配/内部类型参数的类型同义词

cro*_*eea 4 haskell types pattern-matching synonym type-parameter

我的代码中有类似于这个类的东西.在我的情况下,将'作为另一个参数添加到类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
Run Code Online (Sandbox Code Playgroud)

对于这个特定的例子Foo,我希望a'以这种方式相关.我想出这个工作的唯一方法是添加一个带有"明显"类型同义词的"虚拟"类:

class DClass d where
   type DType d

instance DClass (D b) where
    type DType (D b) = b
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

问题是我必须为我的特定数据类型创建一个完整的类(和实例),以表达(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
Run Code Online (Sandbox Code Playgroud)

或者甚至可能在不使用类型同义词的情况下表达此约束的一些更好的方式.愚蠢的是,我应该被迫创建一个带有单个实例的类型同义词的(开放)类来实现这一点,并且其他人可能潜在地创建我不想要的新实例是不安全的.

至少,是否会有一些规范的方法将"模式匹配类型同义词"转换为DClass上面的类/实例?

Nat*_*ell 5

重量稍轻,使用类型系列:

type family DParam d :: *
type instance DParam (D b) = b
Run Code Online (Sandbox Code Playgroud)

不确定你现在能不能做得更好......