在函数签名中隐藏多参数类型类的一个类型参数

Kra*_*ntz 6 haskell typeclass

假设我有一个多参数类型类:

class B b => C a b | a -> b where
    getB :: a -> (T, b)
Run Code Online (Sandbox Code Playgroud)

然后我想要一个功能:

f :: C a b => a -> c
f = g . getB
Run Code Online (Sandbox Code Playgroud)

它使用其他功能g :: B b => (T, b) -> cgetB,因此一个实例C a b是必要的.

(免责声明:真正的问题要复杂得多,上面提到的只是简化版.)

问题是,鉴于功能依赖性C a b | a -> b,我们知道b可以完全决定a,所以理论上我应该可以不提b类型f(因为它不在别处使用,但在实例中C a b),但我没有发现任何实现这一目标的方法.

还要注意,由于B b类中存在约束C,我认为我不能使用TypeFamilies扩展,因为它的语法无法使类型约束生效B b.

那么有什么办法可以隐藏b这个函数用户的实现细节(不相关的类型参数)f

Li-*_*Xia 7

使用TypeFamilies,您可以重写C为单参数类,如下所示:

class B (BOf a) => C a where
  type BOf a :: *
  getB :: a -> (T, BOf a)
Run Code Online (Sandbox Code Playgroud)

这为您提供了更好看的约束f:

f :: C a => a -> c
Run Code Online (Sandbox Code Playgroud)

(遗憾的是)无法省略多参数类的参数以获得类似的结果.

  • 这就是说,没有办法做某件事的麻烦......有人可能会遇到一些比你甚至不愿意想到的更愚蠢的东西. (3认同)