Why is type "Integer -> Integer" and not "(Num a) => a -> a"?

Hi! I have a problem with understanding some types given by ghc and hugs. The file loaded is: f1 = \x -> x * 2 f2 x = x * 2 After they are loaded I get the following from ghci *Main> :t f1 f1 :: Integer -> Integer *Main> :t f2 f2 :: (Num a) => a -> a *Main> :t \x -> x * 2 \x -> x * 2 :: (Num a) => a -> a I do not understand why f1 is given Integer -> Integer as a type and not the polymorphic (Num a) => a -> a. I believed that f1, f2 and the lambda expression should all have the same type. Similar output to that above is given by Hugs. Thanks, Dag Hovland

Hi! That's very weird, I don't have a good answer (and fortunately there are far smarter people on this list who will have a better answer...) but my instincts say it has to do with defaulting. When GHC sees a literal digit, it tries to guess what it's type should be, first via inference, but if that returns a polymorphic type (like `Num a => a` or something) it will "default" to a particular type, for literal whole positive/negative numbers, it defaults to `Integer`. My guess is that, defining in GHCi
let f x = x * 2 let g = \x -> x * 2
the former doesn't default to anything (it just does inference) since it's a function definition, and the latter defaults the '2' to an Integer because it's a value -- or some suitable analog of that situation. What will really blow your mind, try having GHCi inspect the type of
:t \x -> x * 2
(the defn. of `g` w/o the let...) Short answer, I have no idea, but I think it has to do with defaulting. /Joe On Nov 12, 2009, at 3:37 AM, Dag Hovland wrote:
Hi!
I have a problem with understanding some types given by ghc and hugs. The file loaded is:
f1 = \x -> x * 2 f2 x = x * 2
After they are loaded I get the following from ghci
*Main> :t f1 f1 :: Integer -> Integer *Main> :t f2 f2 :: (Num a) => a -> a *Main> :t \x -> x * 2 \x -> x * 2 :: (Num a) => a -> a
I do not understand why f1 is given Integer -> Integer as a type and not the polymorphic (Num a) => a -> a. I believed that f1, f2 and the lambda expression should all have the same type. Similar output to that above is given by Hugs.
Thanks,
Dag Hovland _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On Thursday 12 November 2009 01:45:08 am Joe Fredette wrote:
My guess is that, defining in GHCi
let f x = x * 2 let g = \x -> x * 2
the former doesn't default to anything (it just does inference) since it's a function definition, and the latter defaults the '2' to an Integer because it's a value -- or some suitable analog of that situation.
Hmm. Would that also explain this? Prelude> let f1 x = x * 2 Prelude> :type f1 f1 :: (Num a) => a -> a Prelude> let f2 = \x -> f1 x Prelude> :type f2 f2 :: Integer -> Integer Shawn.

On Thu, Nov 12, 2009 at 7:06 AM, Shawn Willden
Hmm. Would that also explain this?
Prelude> let f1 x = x * 2 Prelude> :type f1 f1 :: (Num a) => a -> a Prelude> let f2 = \x -> f1 x Prelude> :type f2 f2 :: Integer -> Integer
Yes, that's the same monomorphism restriction. Also, note that you are defaulting to Integer here: Prelude> :s -Wall Prelude> let f1 x = x * 2 Prelude> :t f1 f1 :: (Num a) => a -> a Prelude> let f2 = \x -> f1 x <interactive>:1:15: Warning: Defaulting the following constraint(s) to type `Integer' `Num a' arising from a use of `f1' at <interactive>:1:15-18 In the expression: f1 x In the expression: \ x -> f1 x In the definition of `f2': f2 = \ x -> f1 x Prelude> let f3 :: Int -> Int; f3 = \x -> f1 x Prelude> let f4 :: Num a => a -> a; f4 = \x -> f1 x I find -Wall very useful. Relatively few times it gets annoying. HTH, -- Felipe.

On Thu, Nov 12, 2009 at 9:37 AM, Dag Hovland
Hi!
I have a problem with understanding some types given by ghc and hugs. The file loaded is:
f1 = \x -> x * 2 f2 x = x * 2
After they are loaded I get the following from ghci
*Main> :t f1 f1 :: Integer -> Integer *Main> :t f2 f2 :: (Num a) => a -> a *Main> :t \x -> x * 2 \x -> x * 2 :: (Num a) => a -> a
This is called the monomorphism restriction, it's a rule that state a binding _without_parameters_ shall be inferred of a monomorphic type unless an explicit signature is given. There are several reasons for it, some of efficiency (polymorphism has a cost) and some of a more technical nature, refer to the Haskell Report for a more detailed explanation. Some Haskellers think this restriction is no longer required, that GHC is now often intelligent enough to alleviate the cost of polymorphism, that the technical reasons are not really all that pertinent and that the default should be to infer the more general type in all case rather than confuse beginners and oblige experts to put explicit signatures. It is already possible to deactivate the restriction by using the -XNoMonomorphismRestriction argument (or putting the equivalent language pragma in the code itself or in the cabal description file) and making this the default is discussed for Haskell' (the future standard for Haskell). In the meantime, it is a good idea to put ":set -XNoMonomorphismRestriction" in your .ghci file since most usage of GHCi would only hit the disadvantages of this rule and reap no benefits from it. -- Jedaï
participants (5)
-
Chaddaï Fouché
-
Dag Hovland
-
Felipe Lessa
-
Joe Fredette
-
Shawn Willden