import Data.Constraint
reify :: (c' :- c) -> (c => a) -> (c' => a)
reify cons f = case cons of Sub d -> case d of Dict -> f
使用reify
,我可以将约束c
减弱为约束c'
,前提是证明c'
暗示着c
。
现在,我想要一个Rank2
的变体:
-- reify2 Rank2's reify
reify2 :: (forall r1. c' r1 :- c r1) ->
(forall r2. c r2 => a) ->
(forall r3. c' r3 => a)
reify2 cons f = ???
但是,即使必须“明显”可行,我也无法实现该功能。
答案 0 :(得分:2)
可以使用ScopedTypeVariables+TypeApplications
来消除歧义,尽管您需要重新排列reify2
的参数,将类型参数放在范围内。
{-# LANGUAGE AllowAmbiguousTypes, RankNTypes, ConstraintKinds, GADTs, ScopedTypeVariables, TypeApplications, TypeOperators #-}
data Dict c where
Dict :: c => Dict c
data c :- d where
Sub :: (c => Dict d) -> c :- d
reify2 :: forall r3 c c' a. c' r3 =>
(forall r1. c' r1 :- c r1) ->
(forall r2. c r2 => a) ->
a
reify2 cons f =
case cons @r3 of
Sub Dict -> f @r3