I'm beginning Haskell... I tried to write the following trivial function in two different ways, letting Haskell decide the types, and the type system does something different in each case. What is the explanation for that behavior?
Prelude> let f x = 2 * x
Prelude> let g = (2*)
Prelude> :info f
f :: Num a => a -> a -- Defined at <interactive>:1:5
Prelude> :info g
g :: Integer -> Integer -- Defined at <interactive>:1:5
Thanks!
This is known as the monomorphism restriction.
Basically, it means that top-level bindings that look like x =
are forced to be non-polymorphic, unless you specify a type signature. Bindings with arguments, i.e. f x =
are not affected. See the link for details as to why this restriction exists.
Usually, you get an error message when the restriction is applied, but in this case GHCi is able to use type defaulting to change the type Num a => a
to Integer
.
The easiest way to dodge it is to either use an explicit type signature, or put
{-# LANGUAGE NoMonomorphismRestriction #-}
at the top of your module, or run GHCi with -XNoMonomorphismRestriction
.
As others have pointed out, this is caused by something called the "Monomorphism Restriction".
MR can be useful for writers of Haskell compilers, and there is controversy about whether or not it is worthwhile to have in the language in general. But there is one thing everyone agrees: at the GHCi prompt, MR is nothing but a nuisance.
MR will probably be turned off by default in this context in an upcoming version of GHC. For now, you should disable it in GHCi by creating a text file called ".ghci
" in your home directory that contains a line like this:
:set -XNoMonomorphismRestriction
Because the definition of g
doesn't explicitly name its arguments, you run into the monomorphism restriction, preventing g
from being polymorphic and (in this case) causing GHC to default to Integer
.
来源:https://stackoverflow.com/questions/6052670/transforming-a-function-to-point-free-style-changes-its-type