Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Another type-fu hitch

Tags:

haskell

trying to understand how is the final signature inferred:

GHCi> :t (+)
(+) :: Num a => a -> a -> a
GHCi> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
GHCi> :t (<*>) (+)
(<*>) (+) :: Num b => (b -> b) -> b -> b

(a' -> a' -> a') has to be unified with f (a -> b), so f is probably of type ((->) r):

(<*>) :: Applicative ((->) r) => r -> (a -> b) -> (r -> a) -> (r -> b)
(<*>) (+) ~ a' -> (a' -> a') -> (a' -> a') -> (a' -> a')
(<*>) (+) :: (a' -> a') -> (a' -> a') -- ^^^ got stuck here

Can anybody explain how to get the final type ?

Thanks.

like image 808
David Unric Avatar asked Aug 22 '12 17:08

David Unric


1 Answers

The problem you are having is with the right associativity of ->. Consider the type of <*>:

<*> :: (Applicative f) => f (a -> b) -> f a -> f b

With f a equal to r -> a, we have

<*> :: f (a -> b) -> f a -> f b
    :: (r -> (a -> b)) -> (r -> a) -> (r -> b)
    :: (r -> a -> b) -> (r -> a) -> (r -> b) -- This is the key line

Notice that it went from (r -> (a -> b)) -> other stuff to (r -> a -> b) -> other stuff, not r -> (a -> b) -> other stuff. We can remove the inner parentheses because they are on the right of an arrow, but we cannot remove the outer parentheses, as they are on the left of an arrow.

Now, (+) :: (Num a) => a -> a -> a. This fits perfectly with the first argument of <*> when r is the same as a is the same as b and they all are numbers. All together, we get that

(<*>) (+) :: (Num a) => (a -> a) -> (a -> a)
          :: (Num a) => (a -> a) -> a -> a

Note again that I am removing parentheses on the right, but not on the left of the arrow.

like image 53
gereeter Avatar answered Nov 17 '22 11:11

gereeter