[Haskell-beginners] flip lookup in ghci
felipe.lessa at gmail.com
Fri Feb 20 08:06:07 EST 2009
Let's try to see what is going on using GHCi 6.10.1:
Prelude> :t lookup
lookup :: (Eq a) => a -> [(a, b)] -> Maybe b
Prelude> :t flip lookup
flip lookup :: (Eq a) => [(a, b)] -> a -> Maybe b
Everything ok. Lets try binding:
Prelude> let f = flip lookup
Prelude> :t f
f :: [((), b)] -> () -> Maybe b
Woops. Whenever you see a type of a function becoming less polymorphic
than you expected, try adding a parameter:
Prelude> let g x = flip lookup x
Prelude> :t g
g :: (Eq a) => [(a, b)] -> a -> Maybe b
Nice! Let's try again without the monomorphism restriction
Prelude> :s -XNoMonomorphismRestriction
Prelude> let h = flip lookup
Prelude> :t h
h :: (Eq a) => [(a, b)] -> a -> Maybe b
Prelude> :s -XMonomorphismRestriction
So, that's where the culprit lies! As we declared 'f' without a type
signature and without explicit arguments, the monomorphism restriction
didn't let us overload our function with the 'Eq' class.
Note that if we activated all warnings, GHC would tell us that
something is wrong:
Prelude> :s -Wall
Prelude> let j = flip lookup
Warning: Defaulting the following constraint(s) to type `()'
`Eq a' arising from a use of `lookup' at <interactive>:1:13-18
In the first argument of `flip', namely `lookup'
In the expression: flip lookup
In the definition of `j': j = flip lookup
We can't just remove the 'Eq' constraint, if we want to refine the
type of 'lookup' then we need to supply something that implements
'Eq'. As GHC doesn't know what you want to do, it just defaults to ().
If, for example, you used the new function in the same let-binding,
GHC would infer another type and show no warnings:
Prelude> let k = flip lookup; l = k  (1 :: Int)
Prelude> :t k
k :: [(Int, b)] -> Int -> Maybe b
But note that even if you use the function where you defined it, it
can't be polymorphic
Prelude> let m = flip lookup; n = m  (1 :: Int); o = m  (1 :: Double)
Couldn't match expected type `Int' against inferred type `Double'
In the second argument of `m', namely `(1 :: Double)'
In the expression: m  (1 :: Double)
In the definition of `o': o = m  (1 :: Double)
In short: add an explicit parameter or use a type signature. =)
Hope that helps!
More information about the Beginners