在vinyl库中,有一个RecAll
类型族,让我们要求部分应用的约束对于类型级别列表中的每个类型都是正确的。例如,我们可以这样写:
myShowFunc :: RecAll f rs Show => Rec f rs -> String
这一切都很可爱。现在,如果我们有未知的约束RecAll f rs c
,c
并且我们知道c x
蕴含d x
(从 ekmett 的约束包中借用语言),我们怎么能得到RecAll f rs d
?
我问的原因是我正在处理一些需要满足几个类型类约束的函数中的记录。为此,我使用了exists包中Control.Constraints.Combine模块中的:&:
组合器。(注意:如果您安装了其他东西,则该软件包将不会构建,因为它依赖于. typeclass broilerplate。例如:contravariant
RecAll f rs (TypeableKey :&: FromJSON :&: TypeableVal) => Rec f rs -> Value
但是,在这个函数的主体内部,我调用了另一个需要较弱约束的函数。它可能看起来像这样:
RecAll f rs (TypeableKey :&: TypeableVal) => Rec f rs -> Value
GHC 看不到第二个语句是从第一个语句开始的。我以为会是这样。我看不到的是如何证明它以实现它并帮助 GHC。到目前为止,我有这个:
import Data.Constraint
weakenAnd1 :: ((a :&: b) c) :- a c
weakenAnd1 = Sub Dict -- not the Dict from vinyl. ekmett's Dict.
weakenAnd2 :: ((a :&: b) c) :- b c
weakenAnd2 = Sub Dict
这些工作正常。但这就是我卡住的地方:
-- The two Proxy args are to stop GHC from complaining about AmbiguousTypes
weakenRecAll :: Proxy f -> Proxy rs -> (a c :- b c) -> (RecAll f rs a :- RecAll f rs b)
weakenRecAll _ _ (Sub Dict) = Sub Dict
这不编译。有没有人知道一种方法来获得我正在寻找的效果。如果它们有帮助,这里是错误。另外,我Dict
在我的实际代码中有一个合格的导入,所以这就是它提到的原因Constraint.Dict
:
Table.hs:76:23:
Could not deduce (a c) arising from a pattern
Relevant bindings include
weakenRecAll :: Proxy f
-> Proxy rs -> (a c :- b c) -> RecAll f rs a :- RecAll f rs b
(bound at Table.hs:76:1)
In the pattern: Constraint.Dict
In the pattern: Sub Constraint.Dict
In an equation for ‘weakenRecAll’:
weakenRecAll _ _ (Sub Constraint.Dict) = Sub Constraint.Dict
Table.hs:76:46:
Could not deduce (RecAll f rs b)
arising from a use of ‘Constraint.Dict’
from the context (b c)
bound by a pattern with constructor
Constraint.Dict :: forall (a :: Constraint).
(a) =>
Constraint.Dict a,
in an equation for ‘weakenRecAll’
at Table.hs:76:23-37
or from (RecAll f rs a)
bound by a type expected by the context:
(RecAll f rs a) => Constraint.Dict (RecAll f rs b)
at Table.hs:76:42-60
Relevant bindings include
weakenRecAll :: Proxy f
-> Proxy rs -> (a c :- b c) -> RecAll f rs a :- RecAll f rs b
(bound at Table.hs:76:1)
In the first argument of ‘Sub’, namely ‘Constraint.Dict’
In the expression: Sub Constraint.Dict
In an equation for ‘weakenRecAll’:
weakenRecAll _ _ (Sub Constraint.Dict) = Sub Constraint.Dict