I'm manipulating proofs of coercibility:
data a ~=~ b where
IsCoercible :: Coercible a b => a ~=~ b
infix 0 ~=~
sym :: (a ~=~ b) -> (b ~=~ a)
sym IsCoercible = IsCoercible
instance Category (~=~) where
id = IsCoercible
IsCoercible . IsCoercible = IsCoercible
coerceBy :: a ~=~ b -> a -> b
coerceBy IsCoercible = coerce
I can trivially prove Coercible a b => forall x. Coercible (a x) (b x)
introduce :: (a ~=~ b) -> (forall x. a x ~=~ b x)
introduce IsCoercible = IsCoercible
But not the converse, (forall x. Coercible (a x) (b x)) => Coercible a b)
isn't quite as free:
eliminate :: (forall x. a x ~=~ b x) -> (a ~=~ b)
eliminate IsCoercible = IsCoercible
{-
• Could not deduce: Coercible a b
arising from a use of ‘IsCoercible’
from the context: Coercible (a x0) (b x0)
bound by a pattern with constructor:
IsCoercible :: forall k (a :: k) (b :: k).
Coercible a b =>
a ~=~ b,
in an equation for ‘eliminate’
-}
I'm fairly certain my claim is valid (though I'm open to being disproven), but I'm not having any bright ideas as to how to prove it within Haskell short of unsafeCoerce
.
No, you can't. As Dominique Devriese and HTNW hint in their comments, GHC doesn't admit that inference at all. This more demanding version won't compile:
{-# language QuantifiedConstraints, RankNTypes #-}
import Data.Coerce
import Data.Type.Coercion
eliminate :: (forall a. Coercible (f a) (g a)) => Coercion f g
eliminate = Coercion
Your version is even more doomed. To pattern match on the polymorphic Coercion
(or ~=~
) argument, it must be instantiated to a particular type. GHC will instantiate it to f Any ~=~ g Any
, which is then monomorphic and therefore doesn't prove what you want it to. Since GHC Core is typed, that won't fly.
Side note: I find it intensely frustrating that there's no way to write
f :: (forall a. c a :- d a)
-> ((forall a. c a => d a) => r)
-> r
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With