Below is a simplified version of a very similar problem I'm facing.
Consider the following types, and the function f1
:
{-# LANGUAGE RankNTypes #-}
newtype D t = D t deriving Functor
newtype T t = T { getT :: t }
f1 :: (forall t'. t' -> D t') -> T t -> D (T t)
Notice that f1
can actually be id
, because if we get passed function that works for all t
we can of course specialise it like so:
f1 = id
Now lets consider the "inverse" function, f2
:
f2 :: (T t -> D (T t)) -> t -> D t
This "unspecialises" the function, which can be implemented as follows:
f2 f x = getT <$> (f (T x))
We can combine f2
and f1
as follows, which is basically an identity function:
g :: (forall t'. t' -> D t') -> t -> D t
g x = f2 (f1 x)
Indeed, g
is pretty much equivalent to the id
function, and indeed we can instead define g
as follows:
g = id
So we've established as f2 . f1 == id
.
But when we write f2 . f1
, I suspect GHC may not compile that down to id
, because, f2
at least does some non trivial work.
I'd like to write a rewrite rule for f2 . f1
, and here's my attempt:
{-# RULES
"f2f1" forall x. f2 (f1 x) = g x
#-}
As g
as can be defined as id
I figured this might be good.
But unfortunately this fails to compile. I suspect this is due to the higher ranked type in f1
.
I realise if I changed the type signature of f1
like follows:
f1 :: (t -> D t) -> T t -> D (T t)
f1 f x = T <$> f (getT x)
I could write a rewrite rule like follows:
{-# RULES
"f2f1" forall x. f2 (f1 x) = x
#-}
But now whenever I use f1
it isn't just id
, but quite a bit more complex.
Is there a way to write a rewrite rule like f2 . f1 == id
, without giving f1
an non id
style implementation?
Further information:
Note that in my actual problem, both D
and T
are not newtypes.
D
is any Functor f
, and T
is actually a Coyoneda
, following on from this previous question regarding newtype deriving.
Polymorphic free variables in RULES
must have type signatures. Simply use
{-# RULES
"f2/f1" forall (x :: forall t. t -> D t). f2 (f1 x) = x
#-}
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