4

I am studying haskell. Could somebody explain how the two types are inferred and what does Num (a -> a) mean?

liftM2 (==) id :: Eq a => (a -> a) -> a -> Bool


(\x->x+1) id :: Num (a -> a) => a -> a
ErikR
  • 51,541
  • 9
  • 73
  • 124
user3822769
  • 151
  • 6
  • 1
    possible duplicate of [How to use (->) instances of Monad and confusion about (->)](http://stackoverflow.com/questions/5310203/how-to-use-instances-of-monad-and-confusion-about) – Cactus Sep 10 '15 at 03:05

1 Answers1

5

In the first case we have

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
(==) :: Eq a => a -> a -> Bool

by setting a1=a and a2=a we get

liftM2 (==) :: (Eq a, Monad m) => m a -> m a -> m Bool

Now the tricky bit is that there is a Monad instance for the function type.

instance Monad ((->) r) where
    return = const
    f >>= k = \ r -> k (f r) r

because of this, a function of type r -> a can be passed where a Monad a => m a is expected. Since id :: a -> a we get r=a, m a = a -> a and m Bool = a -> Bool, resulting in

liftM2 (==) id :: (Eq a) => (a -> a) -> (a -> Bool)

For the second type, what that type signature is saying is that there is a Num instance for the function type (a -> a).

Haskell numeric literals are polymorphic and ((\x -> x + 1) id) is actually syntactic sugar for the following:

((\x -> x + (fromInteger 1)) id)

which, by β-reduction is

id + (fromInteger 1)

This assumes that (fromInteger 1) is a function and that there is a way to add two functions together with the + operator. By default this is not possible but Haskell allows you to define addition for functions if you really want to.

{-# LANGUAGE FlexibleInstances #-}

instance Num (Int -> Int) where
  f + g = \x -> f x + g x
  f * g = \x -> f x * g x
  abs f = \x -> abs (f x)
  fromInteger n = \x -> fromInteger n
  signum f = error "not implemented"


f1 :: Int -> Int
f1 x = x + 1

f2 :: Int -> Int
f2 x = x + 2

f3 :: Int -> Int
f3 = f1 + f2

main = do
  print $ f3 0
hugomg
  • 68,213
  • 24
  • 160
  • 246
  • (id + (fromInteger 1)) 0, which (+) function does compiler choose? If it choose f + g = \x -> f x + g x, (fromInteger 1) 0 will get a error. By the way, you have a typo 'liftM2 (==) if' – user3822769 Sep 10 '15 at 03:14
  • In the example I made I only defined instances for `Int -> Int` so you need to add some type annotations to guide Haskell the correct way, like I did in my `f1+f2` example, where all the functions are annotated. If you use `((fromInteger 1) (0::Int)) :: Int` then it should work – hugomg Sep 10 '15 at 03:25