I asked a question about injection functors in the context of free monads a couple of days ago . The solution proposed there, based on Γ la Carte Data Types , uses a class that is a kind of containment relationship between functors.
-- | Class that represents the relationship between a functor 'sup' containing
-- a functor 'sub'.
class (Functor sub, Functor sup) => sub :-<: sup where
inj :: sub a -> sup a
-- | A functor contains itself.
instance Functor f => f :-<: f where
inj = id
-- | A functor is contained in the sum of that functor with another.
instance (Functor f, Functor g) => f :-<: (Sum f g) where
inj = InL
-- | If a functor 'f' is contained in a functor 'g', then f is contained in the
-- sum of a third functor, say 'h', with 'g'.
instance (Functor f, Functor g, Functor h, f :-<: g) => f :-<: (Sum h g) where
inj = InR . inj
Now consider the following data types:
type WeatherData = String
data WeatherServiceF a = Fetch (WeatherData -> a) deriving (Functor)
data StorageF a = Store WeatherData a deriving (Functor)
And a function with the following type
fetch :: (WeatherServiceF :-<: g) => Free g WeatherData
Where Freecomes from the module Control.Monad.Free.
Then, if I try to use this function as follows:
reportWeather :: Free (Sum WeatherServiceF StorageF) ()
reportWeather = do
_ <- fetch
return ()
I get an overlapping instance error saying:
β’ Overlapping instances for WeatherServiceF
:-<: Sum WeatherServiceF StorageF
arising from a use of βfetchβ
Matching instances:
two instances involving out-of-scope types
instance (Functor f, Functor g) => f :-<: Sum f g
instance (Functor f, Functor g, Functor h, f :-<: g) =>
f :-<: Sum h g
Now I understand that the first is a valid instance, but why is the second considered a valid instance? If I create variables in the second case, I would get
instance ( Functor WeatherServiceF
, Functor StorageF
, Functor WeatherServiceF
, WeatherServiceF :-<: StorageF
) => WeatherServiceF :-<: Sum WeatherServiceF g
, , WeatherServiceF :-<: StorageF. GHC ?
:
{-
{-
{-
{-
{-