7

Playing around in ghci I got the following expression: unlines . map (\(a,b) -> show a ++ " " ++ show b)

Now when I check it via :t I get:

> :t  unlines . map (\(a,b) -> show a ++ " " ++ show b)
unlines . map (\(a,b) -> show a ++ " " ++ show b)
  :: (Show a, Show a1) => [(a, a1)] -> String

So exactly as expected. But now if I try to assign it to some name, I get a more specific signature than the original one:

> let f = unlines . map (\(a,b) -> show a ++ " " ++ show b)
> :t f
f :: [((), ())] -> String

Why does this happen?

viraptor
  • 33,322
  • 10
  • 107
  • 191
  • 1
    See also: [1](http://stackoverflow.com/questions/7055146), [2](http://stackoverflow.com/questions/11439163), [3](http://stackoverflow.com/questions/9714697), [4](http://stackoverflow.com/questions/8434808), [5](http://stackoverflow.com/questions/7799345), [6](http://stackoverflow.com/questions/8262020), [7](http://stackoverflow.com/questions/8655900), [8](http://stackoverflow.com/questions/11003535). I'm honestly not sure which (if any) of these to mark this a duplicate of. – Daniel Wagner Mar 16 '13 at 22:40

2 Answers2

12

Because of the monomorphism restriction, definitions of the form x = ... (no parameters) are given a monomorphic (i.e. non-polymorphic) type, which usually involves some defaulting as mentioned in the other answer.

To prevent this from happening, either add a type signature to your definition, or disable the monomorphism restriction using :set -XNoMonomorphismRestriction. You can add this to your .ghci file to have it run automatically on startup until it gets disabled by default in GHCi in some future version.

Community
  • 1
  • 1
hammar
  • 138,522
  • 17
  • 304
  • 385
  • 1
    Or eta expand; i.e. `let f x = unlines . map (\(a,b) -> show a ++ " " ++ show b) $ x` – luqui Mar 16 '13 at 17:44
4

Defaulting rules.

When you type stuff in GHCi, it attempts to apply default types. IIRC, for things with a Num constraint it picks Integer, for Fractional it picks Double, and for everything else it picks ().

If you write this in a Haskell source file and load it into GHCi, this doesn't happen (I believe).

I think you can also say something like default Int to change the defaulting rules on a per-module basis.

MathematicalOrchid
  • 61,854
  • 19
  • 123
  • 220