Function in type constraint

Viewed 52

Checking type of (Just (+2)) <*> (Just (+2)) I have found it has constraint Num (a -> a), which is confusing to what Num (a -> a) should mean here

(Just (+2)) <*> (Just (+2)) :: (Num a, Num (a -> a)) => Maybe (a -> a)
1 Answers

Let us analyze the types first. Just (+2) has type Just (+2) :: Num a => Maybe (a -> a), and (<*>) has type (<*>) :: Applicative f => f (c -> d) -> f c -> f d .

If we thus construct an expression (<*>) (Just (+2)) (Just (+2)), then the type is equivalent to:

(<*>) :: Applicative f => f (c -> d)     -> f c            -> f d
Just (+2) :: Num a =>     Maybe (a -> a)
Just (+2) :: Num b =>                       Maybe (b -> b)
-----------------------------------------------------------------
f ~ Maybe, a ~ c ~ d, c ~ (b -> b)

It thus means that the applicative type is Maybe, and that a, c and d are the same type, and that c is equivalent to (b -> b). Since there is a type constraint Num a, and a ~ c, it means that the type contraint also holds for c, and thus that Num b => (b -> b) needs to be an instance of the Num typeclass. The result of this type is thus:

(<*>) (Just (+2)) (Just (+2)) :: Num b => Maybe (b -> b)

This makes sense, since the outcome of Just (+2) <*> Just (+2) will be Just ((+2) + 2), and since (+) has type (+) :: Num a => a -> a -> a, and therefore it thus expects that the first operand (+2) which is a function, should be of a type that is an instance of Num.

Related