
I was trying to convert a function, f1 x l = map (\y -> y*x) l to so-called point-free style, but in reducing it I found two functions that seemed to work the same, until I discovered they have different types, and aren't equivalent: f1a x = map (*x) -- has type (Num a) => a -> [a] -> [a] f1b = \x -> map (*x) -- has type Integer -> [Integer] -> [Integer] Can someone help me understand why the latter has a more restrictive type? If I add the type signature "f1b :: (Num a) => a -> [a] -> [a]", they are once again equivalent, but am confused about what's going on. If this is MR, what exactly am I overloading here? I read through http://www.haskell.org/haskellwiki/Monomorphism_restriction and http://www.cs.auckland.ac.nz/references/haskell/haskell-intro-html/pitfalls..... If anyone has a good reading recommendation here, I'd love to see it. Because if this is MR, I'm not understanding what MR is correctly. Also, They don't generate a type error, which makes me think it is not MR, but something else. Thanks, Mike

On Dec 17, 2009, at 17:56 , Mike Erickson wrote:
f1a x = map (*x) -- has type (Num a) => a -> [a] -> [a]
f1b = \x -> map (*x) -- has type Integer -> [Integer] -> [Integer]
Can someone help me understand why the latter has a more restrictive type?
That is indeed the monomorphism restriction. In very short: if a top level form (like your f1, f1a, f1b) takes no arguments and does not have an explicit type, its type is restricted according to defaulting; if no suitable default exists, it is rejected. In this case, defaulting gave it the type Integer because Integer is the first type in the defaults list that allows the declaration to typecheck. (The default "defaults list" is Integer, Double, and in recent GHC () (the null/unit type). -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Am Donnerstag 17 Dezember 2009 23:56:13 schrieb Mike Erickson:
I was trying to convert a function,
f1 x l = map (\y -> y*x) l
to so-called point-free style, but in reducing it I found two functions that seemed to work the same, until I discovered they have different types, and aren't equivalent:
f1a x = map (*x) -- has type (Num a) => a -> [a] -> [a]
f1b = \x -> map (*x) -- has type Integer -> [Integer] -> [Integer]
Can someone help me understand why the latter has a more restrictive type?
Indeed it's the monomorphism restriction. In f1a x = map (*x) , f1a is bound by a *function binding* (bound name and (>= 1) pattern on the left of '='), thus it has a polymorphic type. In f1b = \x -> map (*x) (btw, you can further point-free this as map . (*)), f1b is bound by a *simple pattern binding*, thus the monomorphism restriction says that without a type signature, it must have a monomorphic type. Type inference determines the type (Num a) => a -> [a] -> [a] for the function. This is a "type class polymorphic" type [the monomorphism restriction doesn't restrict unconstrained types, only if a type class is involved does it kick in], hence by the monomorphism restriction, it must have a monomorphic type. The type class is Num, thus by the default defaulting rules, for (Num a), a is instantiated as Integer, hence f1b :: Integer -> [Integer] -> [Integer]
If I add the type signature "f1b :: (Num a) => a -> [a] -> [a]", they are once again equivalent, but am confused about what's going on. If
The monomorphism restriction only applies to functions without a type signature.
this is MR, what exactly am I overloading here?
I read through http://www.haskell.org/haskellwiki/Monomorphism_restriction and http://www.cs.auckland.ac.nz/references/haskell/haskell-intro-html/pitfalls .html. If anyone has a good reading recommendation here, I'd love to see it.
Read the report:http://haskell.org/onlinereport/decls.html#sect4.5.5 (start at section 4.5.4) and http://haskell.org/onlinereport/decls.html#sect4.4.3 for pattern and function bindings. It's a little technical, but with the other resources it should be understandable. In short, if you declare a function point-free and the inferred type involves type classes, it cannot be polymorphic unless you give a type signature. Without a type signature, the implementation tries to determine a monomorphic type from the inferred polymorphic type by the defaulting rules (http://haskell.org/onlinereport/decls.html#sect4.3.4). If that succeeds, this type is given to the function, otherwise it's a type error and the module doesn't compile.
Because if this is MR, I'm not understanding what MR is correctly. Also, They don't generate a type error, which makes me think it is not MR, but something else.
Thanks,
Mike

On Thu, Dec 17, 2009 at 3:45 PM, Daniel Fischer
Am Donnerstag 17 Dezember 2009 23:56:13 schrieb Mike Erickson:
I was trying to convert a function,
f1 x l = map (\y -> y*x) l
to so-called point-free style, but in reducing it I found two functions that seemed to work the same, until I discovered they have different types, and aren't equivalent:
f1a x = map (*x) -- has type (Num a) => a -> [a] -> [a]
f1b = \x -> map (*x) -- has type Integer -> [Integer] -> [Integer]
Can someone help me understand why the latter has a more restrictive type?
Indeed it's the monomorphism restriction. [...]
This was very helpful. I think I understand, although it's still digesting.
In short, if you declare a function point-free and the inferred type involves type classes, it cannot be polymorphic unless you give a type signature. Without a type signature, the implementation tries to determine a monomorphic type from the inferred polymorphic type by the defaulting rules (http://haskell.org/onlinereport/decls.html#sect4.3.4). If that succeeds, this type is given to the function, otherwise it's a type error and the module doesn't compile.
Shortly after posting (of course) I discovered the online report and 4.5.4 and 4.5.5 were helpful as well. Thanks to all that responded, Mike

On Thu, Dec 17, 2009 at 04:46:34PM -0800, Mike Erickson wrote:
On Thu, Dec 17, 2009 at 3:45 PM, Daniel Fischer
wrote: Am Donnerstag 17 Dezember 2009 23:56:13 schrieb Mike Erickson:
I was trying to convert a function,
f1 x l = map (\y -> y*x) l
to so-called point-free style, but in reducing it I found two functions that seemed to work the same, until I discovered they have different types, and aren't equivalent:
f1a x = map (*x) -- has type (Num a) => a -> [a] -> [a]
f1b = \x -> map (*x) -- has type Integer -> [Integer] -> [Integer]
Can someone help me understand why the latter has a more restrictive type?
Indeed it's the monomorphism restriction. [...]
This was very helpful. I think I understand, although it's still digesting.
In short, if you declare a function point-free and the inferred type involves type classes, it cannot be polymorphic unless you give a type signature. Without a type signature, the implementation tries to determine a monomorphic type from the inferred polymorphic type by the defaulting rules (http://haskell.org/onlinereport/decls.html#sect4.3.4). If that succeeds, this type is given to the function, otherwise it's a type error and the module doesn't compile.
Shortly after posting (of course) I discovered the online report and 4.5.4 and 4.5.5 were helpful as well.
I should point out that the monomorphism restriction will probably be removed from a future version of the language standard. I recommend turning it off, especially in ghci (by putting ':set -XNoMonomorphismRestriction' in your .ghci file)---it is rarely useful and just confuses people. -Brent
participants (4)
-
Brandon S. Allbery KF8NH
-
Brent Yorgey
-
Daniel Fischer
-
Mike Erickson