Reputation: 843
import Data.Constraint
reify :: (c' :- c) -> (c => a) -> (c' => a)
reify cons f = case cons of Sub d -> case d of Dict -> f
Using reify
, I can weaken a constraint c
to a constraint c'
given proof that c'
implies c
.
Now, I want a Rank2
variant of this:
-- reify2 Rank2's reify
reify2 :: (forall r1. c' r1 :- c r1) ->
(forall r2. c r2 => a) ->
(forall r3. c' r3 => a)
reify2 cons f = ???
But I'm unable to implement such a function, even though it must "clearly" be possible.
Upvotes: 1
Views: 103
Reputation: 33399
The ambiguity can be lifted using ScopedTypeVariables+TypeApplications
, although you need to reorder the arguments of reify2
, putting the type arguments first to put them in scope.
{-# 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
Upvotes: 2