As we known Maybe's kind is *->*.
So it could be a instance of Functor
instance Functor Maybe where
fmap :: f -> Maybe a -> Maybe b
fmap f Nothing = Nothing
fmap f (Maybe x) = Maybe (f x)
The first example:
{-# LANGUAGE TypeSynonymInstances #-}
type MaybeAlias a = Maybe
instance {-# OVERLAPPING #-} Functor (MaybeAlias Int) where
fmap f functor = undefined
Under the effect of TypeSynonymInstances extension (almost like a String replace), it equals
instance {-# OVERLAPPING #-} Functor Maybe where
fmap f functor = undefined
It is ok, because allow fully applied type synonyms to be used in instance heads
See the other example:
{-# LANGUAGE TypeSynonymInstances #-}
type MaybeAlias a b = Maybe
What's the kind of MaybeAlias Int now? It's kind is *->*->*.
Why?
As @heatsink comment above:
A partially applied synonym is effectively a function whose inputs are the un-applied types and whose output is a type
Explain it now:
Under the defintion of type MaybeAlias a b = Maybe :
MaybeAlias like a partially applied function:
(MaybeAlias) :: a -> b -> Maybe
MaybeAlias Int like a partially applied function:
(MaybeAlias Int) :: b -> Maybe
The Maybe 's kind is * -> *, b 's kind is *.
So MaybeAlias Int 's kind is * -> (* -> *) .
And * -> (* -> *) equals * -> * -> *.
The root cause why the below code not working, because Functor typeclass only accept type that has kind * -> *, not * -> * ->*!
{-# LANGUAGE TypeSynonymInstances #-}
type MaybeAlias a b = Maybe
instance {-# OVERLAPPING #-} Functor (MaybeAlias Int) where
fmap f functor = undefined
Why the below code not working?
class Example e where
thingy :: a -> b -> e a b
-- legit, but awkward
newtype FuncWrapper e a b = FuncWrapper { ap :: a -> e a b }
instance (Example e) => Example (FuncWrapper e) where
thingy _ = FuncWrapper . flip thingy
funcWrapperUse :: (Example e) => e Int String
funcWrapperUse = thingy 1 "two" `ap` 3 `ap` 4 `ap` 5
-- not legal, but a little easier to use
type FuncSynonym e a b = a -> e a b
instance (Example e) => Example (FuncSynonym e) where
thingy _ = flip thingy
funcSynonymUse :: (Example e) => e Int String
funcSynonymUse = thingy 1 "two" 3 4 5
Example typeclass accept a type that has kind * -> * -> *
FuncSynonym like a partially applied function:
FuncSynonym :: e -> a -> b -> (a -> e a b)
FuncSynonym e like a partially applied function:
(FuncSynonym e):: a -> b -> ( a -> e a b)
a 's kind is *,
b 's kind is *,
a -> e a b 's kind *
(FuncSynonym e)'s kind is * -> * -> *
Example typeclass accept a type that has kind * -> * -> *, but why still not work?
It's the other reason in ghc issue 785 and comment