假设我有一个多参数类型类:
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) -> c和getB,因此一个实例C a b是必要的.
(免责声明:真正的问题要复杂得多,上面提到的只是简化版.)
问题是,鉴于功能依赖性C a b | a -> b,我们知道b可以完全决定a,所以理论上我应该可以不提b类型f(因为它不在别处使用,但在实例中C a b),但我没有发现任何实现这一目标的方法.
还要注意,由于B b类中存在约束C,我认为我不能使用TypeFamilies扩展,因为它的语法无法使类型约束生效B b.
那么有什么办法可以隐藏b这个函数用户的实现细节(不相关的类型参数)f?
使用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)
(遗憾的是)无法省略多参数类的参数以获得类似的结果.