Allow deriving multiparameter type classes with representationally equal arguments
This currently works
{-# Language DerivingStrategies, MultiParamTypeClasses, FunctionalDependencies, GeneralizedNewtypeDeriving #-}
import Data.Kind
import Data.Functor.Identity
class SIEVE f p | p -> f where
sIEVE :: p a b -> a -> f b
instance SIEVE Identity (->) where
sIEVE = (Identity .)
newtype ARR a b = ARR (a -> b)
deriving newtype
(SIEVE Identity)
But what if I want a Sieve I ARR
instance, for newtype I a = I a
(which is representationally equal to newtype Identity a = Identity a
)?
{-# Language DerivingStrategies, MultiParamTypeClasses, FunctionalDependencies, GeneralizedNewtypeDeriving, RankNTypes, TypeApplications, ScopedTypeVariables, InstanceSigs #-}
import Data.Kind
import Data.Functor.Identity
import Data.Coerce
class SIEVE f p | p -> f where
sIEVE :: p a b -> a -> f b
instance SIEVE Identity (->) where
sIEVE = (Identity .)
newtype ARR a b = ARR (a -> b)
deriving newtype
(SIEVE I)
newtype I a = I a
generating the following code (this is basically to code generated before, except replacing some Identity
s with I
s
instance SIEVE I ARR where
sIEVE :: forall a b. ARR a b -> (a -> I b)
sIEVE
= coerce
@((a -> b) -> a -> Identity b)
@(ARR a b -> a -> I b)
sIEVE
GHC should be able to recover Identity
due to the functional dependency.