Why does <*> of an instance of Const take two non-functional values?
(<*>) :: Applicative f => f (a -> b) -> f a -> f b Const :: a -> Const a b Monoid m => Applicative (Const * m) Const "a" <*> Const "b" -- yields Const "ab" Const a <*> Const a = Const a <> Const a
My guess is that this behavior must have something to do with the fact that Const
is a binary type constructor where b
never touched (phantom type). But again I don't understand Const * m
because a
(and *
accordingly) seems to be discarded in this case.
source share
First, if it m
has an instance Monoid
, then it Const m
has an instance Applicative
. But Const m
it is still a type constructor, so the type <*>
for Applicative (Const m)
reads
(<*>) :: Const m (a -> b) -> Const m a -> Const m b
Now let's apply this to Const "a"
and Const "b"
:
Const "a"
has a type Const String b
. So here the type variable m
from above takes on a type String
. The value is still polymorphic with respect to, b
and since it does not contain a specific value of that type, the type can still be anything.
In an expression, a Const "a" <*> Const "b"
polymorphic value Const "a"
will be forced to have a type Const String (a->b)
, and a polymorphic value Const "b"
will have a type Const String a
.
So, there really is a type with a function type inside on the left side, only a specific value does not contain a function, for example with a Nothing
type value Maybe (Int -> Int)
.
PS: I don't know where *
it comes from Monoid m => Applicative (Const * m)
. If I print
:info Const
in ghci, I get the line
instance Monoid m => Applicative (Const m)
source share