iceman
iceman

Reputation: 2130

Haskell: function composition resulted in type-mismatch error

TL;DR: What can cause a type-mismatch error in GHCi purely as a result of function composition? It's odd to see GHCi evaluate the following code:

foldl (a . b . c) crackle pop       <- GHCi evaluates this`

...only to give an error after we try to evaluate the following:

let snap = a . b . c                <- GHCi evaluates this
foldl snap crackle pop              <- GHCi reports an error (!)

The longer version:

I am baffled by what I'm observing here in GHCi and am hoping someone can explain it (description included below image):

enter image description here

What do we see above?:

Can someone please help me understand why function composition led to an error (as a result of a type change) in this case? And what should I be doing differently?

Upvotes: 3

Views: 298

Answers (1)

yatima2975
yatima2975

Reputation: 6610

The dynamic duo of ghci's extended defaulting rules and the Dreaded Monomorphism Restriction strike again!

I'm guessing you're using a slightly out-of-date ghci, version 7.6 or earlier.

What happens is that foldingFunction has as most general type

foldingFunction :: Ord a => Map a [b] -> (a,[b]) -> Map a [b]

However, since it's a top-level definition without arguments and your version of ghci still has the monomorphism restriction, this isn't a 'good' type (it's polymorphic because of the context Ord a), and the defaulting rules kick in. ghci tries to find a default instance for Ord a - normally this would fail (since there is no Num-like constraint), but ghci also considers () as a possible default. That works, so if you ask ghci for the type of foldingFunction you'll get

foldingFunction :: Map () [b] -> ((), []) -> Map () []

which is where your type error comes from. (I hope I've guessed correctly!)


There are a couple of ways around this:

  1. Add an argument to foldingFunction: if you use foldingFunction m = (flip $ uncurry (Map.insertWith (++))) m or maybe nicer foldingFunction m (a,bs) = insertWith (++) a bs m it'll start working.
  2. Switch off the monomorphism restriction, either by adding a {-# LANGUAGE NoMonomorphismRestriction #-} pragma at the top of your file, or doing it interactively by entering :set -XNoMonomorphismRestriction at ghci's command line.
  3. Upgrade to a newer version of GHC (7.8.3 does the trick for me).

Both having the DMR off by default and the extended defaulting rules are fairly recent (last couple of years) additions to ghci, so it might even be that the book or text you're using are too old :)

Upvotes: 8

Related Questions