
Thanks for examples and pointers. Since I came from Lisp, it never occurred to me that let and lambda are different constructs in Haskell. I thought that let x = y in f is really (\x -> f) y It turns out that let is about declarations which are not the same as function applications above. So, here is a little followup for this experiment. Prelude> :t (\f -> (f 42, f True)) <interactive>:1:10: No instance for (Num Bool) arising from the literal `42' at <interactive>:1:10-11 Possible fix: add an instance declaration for (Num Bool) In the first argument of `f', namely `42' In the expression: f 42 In the expression: (f 42, f True) If I understand correctly, compiler first checks f 42, and deduces that f must be of type (Num a) => a -> b. Then it checks f True, and it does not satisfy the previously deduced type for f, because type of True is not in Num class. This works: Prelude> :t (\f -> (f 42, f 41.9)) (\f -> (f 42, f 41.9)) :: (Fractional t1) => (t1 -> t) -> (t, t) It just managed to deduce a type for f :: (Fractional t1) => (t1 -> t) And this, of course, works: Prelude> let f = id in (f 42, f True) (42,True) If I understand correctly again, it happens because f is a definition, which gets substituted to f 42 and to f True.