说我有一个多参数类型类:
class B b => C a b | a -> b where
getB :: a -> (T, b)
然后我想要一个功能:
f :: C a b => a -> c
f = g . getB
哪个使用另一个函数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扩展,因为它的语法对类型约束{{1}毫无用处} 为了生活。
那么,有什么方法可以向函数B b
的用户隐藏实现细节(不相关的类型参数b
)?
答案 0 :(得分:7)
使用TypeFamilies
,可以将C
重写为单参数类,如下所示:
class B (BOf a) => C a where
type BOf a :: *
getB :: a -> (T, BOf a)
这为f
带来了更好的外观约束:
f :: C a => a -> c
(遗憾的是)没有办法忽略多参数类的参数以获得相似的结果。
答案 1 :(得分:4)
如果打开.then( ({data}) => {
,则可以创建一个类型别名,让您像这样跳过RankNTypes
:
b
如果需要,您甚至可以在第二个参数内包含更多上下文:
type C' a t = forall b. C a b => t
f :: C' a (a -> c)
f = g . getB
这是非常不标准的。您将需要留下解释性的评论……最终,编写该文本的工作可能比在每次使用f' :: C' a ((Num a, Ord c) => a -> c)
f' = g . getB
时仅包含b
的工作要大。>