I define five functions that seem to me like they should be equivalent (and, therefore, have the same type). But the inferred types are different. I put the following five lines in type-inference.hs:
f1 a b = a + b
f2 a = \b -> a + b
f3 = \a -> \b -> a + b
f4 a = (a+)
f5 = (+)
And then I load up Hugs:
Hugs> :load type-inference.hs
Main> :type f1
f1 :: Num a => a -> a -> a
Main> :type f2
f2 :: Num a => a -> a -> a
Main> :type f3
f3 :: Integer -> Integer -> Integer
Main> :type f4
f4 :: Num a => a -> a -> a
Main> :type f5
f5 :: Integer -> Integer -> Integer
What happened here?
Everything in Haskell has a type, so the compiler can reason quite a lot about your program before compiling it. Unlike Java or Pascal, Haskell has type inference.
Type inference is the process by which Haskell 'guesses' the types for variables and functions, without you needing to specify these types explicitly. Many functional languages feature type inference. There is lots of theory behind type inference — Hindley-Milner type systems and Unification.
Functions can also be passed as arguments or returned (as we have seen). Their types are given in the type signature. *Main> :t map map :: (a -> b) -> [a] -> [b] *Main> :t filter filter :: (a -> Bool) -> [a] -> [a] flip_args :: (a -> b -> c) -> b -> a -> c flip_args f x y = f y x.
If you are using an interactive Haskell prompt (like GHCi) you can type :t <expression> and that will give you the type of an expression.
It is the MonomorphismRestriction at work.
Prelude> let f5 = (+)
Prelude> :t f5
f5 :: Integer -> Integer -> Integer
Prelude> :set -XNoMonomorphismRestriction
Prelude> let f5 = (+)
Prelude> :t f5
f5 :: Num a => a -> a -> a
Because of that, the type synthesizer is forced to default early on some types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With