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.

+3


source share


1 answer


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)

      

+5


source







All Articles