RLE in Haskell: why does the type variable get instantiated?

Hey Haskell-Cafe, I was trying out the code in Dons's article [1], and I noticed a weird thing when doing it in GHCi. When binding the function composition to a variable, the type suddenly changes. I'm not completely sure why this happens. Is this because GHCi is in a monad and wants to find an instance for the type variable? Here's my GHCi session: Prelude> :m +Control.Arrow Prelude Control.Arrow> :m + List Prelude Control.Arrow List> :t map (length &&& head) . group map (length &&& head) . group :: (Eq a) => [a] -> [(Int, a)] Prelude Control.Arrow List> let encode = map (length &&& head) . group Prelude Control.Arrow List> :t encode encode :: [Integer] -> [(Int, Integer)] Thanks, -chris [1]: http://cgi.cse.unsw.edu.au/~dons/blog/2007/07/31

Chris Eidhof wrote:
When binding the function composition to a variable, the type suddenly changes.
Prelude Control.Arrow List> :t map (length &&& head) . group map (length &&& head) . group :: (Eq a) => [a] -> [(Int, a)] Prelude Control.Arrow List> let encode = map (length &&& head) . group Prelude Control.Arrow List> :t encode encode :: [Integer] -> [(Int, Integer)]
You've tripped over the Monomorphism Restriction. http://haskell.org/haskellwiki/Monomorphism_restriction http://haskell.org/onlinereport/decls.html#sect4.5.5 In short, you have to supply a type signature encode :: (Eq a) => [a] -> [(Int, a)] encode = map (length &&& head) . group to get the polymorphic function type when type-classes like Eq or especially Num are involved. Without signature, the compiler will _default_ some the type variables mentioned in the class context to Integer or similar. Note that definitions on the GHCi prompt will receive more defaulting than those in Haskell source files. This is to make things like show [] 1+5 work at the prompt. Also note that the monomorphism restriction only applies to constant applicative forms, i.e. point-free definitions of values. In other words, encode x = map (length &&& head) . group $ x will result in the proper polymorphic type. Regards, apfelmus

On Jul 31, 2007, at 6:00 , apfelmus wrote:
Chris Eidhof wrote:
When binding the function composition to a variable, the type suddenly changes.
Prelude Control.Arrow List> :t map (length &&& head) . group map (length &&& head) . group :: (Eq a) => [a] -> [(Int, a)] Prelude Control.Arrow List> let encode = map (length &&& head) . group Prelude Control.Arrow List> :t encode encode :: [Integer] -> [(Int, Integer)]
In short, you have to supply a type signature
encode :: (Eq a) => [a] -> [(Int, a)] encode = map (length &&& head) . group
let encode :: (Eq a) => [a] -> [(Int,a)]; encode = map (length &&&
Note that you can do this at the GHCi prompt like this: head) . group since you can't use multi-line declarations from the prompt. -- 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

On 31-jul-2007, at 11:38, Chris Eidhof wrote:
Hey Haskell-Cafe,
I was trying out the code in Dons's article [1], and I noticed a weird thing when doing it in GHCi. When binding the function composition to a variable, the type suddenly changes. I'm not completely sure why this happens. Is this because GHCi is in a monad and wants to find an instance for the type variable?
Yes, that is mostly correct. GHCi does defaulting of types, and in this case the type variable defaults to Integer. With regards, Arthur. -- /\ / | arthurvl@cs.uu.nl | Work like you don't need the money /__\ / | A friend is someone with whom | Love like you have never been hurt / \/__ | you can dare to be yourself | Dance like there's nobody watching

On 7/31/07, Chris Eidhof
Hey Haskell-Cafe,
I was trying out the code in Dons's article [1], and I noticed a weird thing when doing it in GHCi. When binding the function composition to a variable, the type suddenly changes. I'm not completely sure why this happens. Is this because GHCi is in a monad and wants to find an instance for the type variable? Here's my GHCi session: [ ... ]
Apfelmus already explained why it happens. I'd like to add one thing. If you are experimenting with GHCi, you can turn the restriction off with the option -fno-monomorphism-restriction. In GHCi itself this is given as follows: Prelude> :set -fno-monomorphism-restriction After giving this and entering the same things as in your original message, the type of encode came out to be as follows: Prelude Control.Arrow Data.List> let encode = map (length &&& head) . group Prelude Control.Arrow Data.List> :t encode encode :: (Eq a) => [a] -> [(Int, a)] This option also saves some typing (of the variety you do on the keyboard!) when you just want to use GHCi as a calculator: Prelude Control.Arrow Data.List> let x = 5 Prelude Control.Arrow Data.List> let y = 6.3 Prelude Control.Arrow Data.List> x*y 31.5 Instead of Integer, the type of x is now x :: (Num t) => t without the restriction, and I don't need to add fromInteger to the multiplication. I don't recommend you to use this option all the time, of course. It's just a convenience. Pekka
participants (5)
-
apfelmus
-
Arthur van Leeuwen
-
Brandon S. Allbery KF8NH
-
Chris Eidhof
-
Pekka Karjalainen