Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't the typeclass constraint be inferred and get ambiguous instead?

For the following code,

func :: Show a => a -> a
func = id

func3 = func . func

the compile complains with messages

Ambiguous type variable `c0' in the constraint:
  (Show c0) arising from a use of `func'
Possible cause: the monomorphism restriction applied to the following:
  func3 :: c0 -> c0 (bound at test.hs:6:1)
Probable fix: give these definition(s) an explicit type signature
              or use -XNoMonomorphismRestriction.

However, querying its type in GHCi works just fine.

*Main> :t func . func
func . func :: Show c => c -> c

What's happening here? Is there any way to have the type of func3 automatically inferred?

p.s. Following the instructions in the message do help, but I don't understand what's going on here.

like image 401
shhyou Avatar asked Feb 09 '14 01:02

shhyou


1 Answers

There are three ways you can compile your code.

Method 1

You can disable the monomorphism restriction.

{-# LANGUAGE NoMonomorphismRestriction #-}

The monomorphism restriction comes into play because func3 is not defined using function syntax. Which leads to method 2:

Method 2

If you had done this instead:

func3 x = func . func $ x

Everything would have been fine. The monomorphism restriction is a rule that protects you from "accidentally" defining a polymorphic value. It is known to be a little too restrictive in some common cases, and it is a deviation from standard Hindley-Milner type inference.

Method 3

Of course, the final thing you can do, is to give your function an explicit type signature.

func3 :: Show a => a -> a
func3 = func . func

The monomorphism restriction means that any value which is declared without function syntax (i.e., the left hand side of the = has no parameters) will not get a polymorphic type derived automatically.

like image 133
Dietrich Epp Avatar answered Oct 21 '22 22:10

Dietrich Epp