[Haskell-beginners] Question about List Type Constraint and Null

Daniel Fischer daniel.is.fischer at googlemail.com
Sat Jan 22 20:49:53 CET 2011


On Saturday 22 January 2011 20:01:19, aditya siram wrote:
> Yes that was a mistake, but the weirder thing is that fixing the type
> sig does nothing to change the behavior described before: it still
> fails to compile with -XNoMonomorphismRestriction and compiles fine if
> it's removed.
>
> It's going to take me a while understand absorb your explanation.

Perhaps the following will help understanding it:

module ReadStuff where

test :: String -> Maybe Int
test s = if null res then
           Nothing
         else
           Just $ fst $ head res
         where
           res = reads s

Prelude> :l ReadStuff
[1 of 1] Compiling ReadStuff        ( ReadStuff.hs, interpreted )

ReadStuff.hs:4:18:
    Ambiguous type variable `a' in the constraint:
      (Read a) arising from a use of `res'
    Probable fix: add a type signature that fixes these type variable(s)
    In the first argument of `null', namely `res'
    In the expression: null res
    In the expression:
      if null res then Nothing else Just $ fst $ head res
Failed, modules loaded: none.


The inferred type for res is

res :: Read a => [(a,String)]

with an implicit (forall a.).
The value of `null res' for a given String obviously depends on the type at 
which res is used.
To make test work, the type of res to use there has to be determined 
somehow.

The natural way is to force res in line 4 to have the same type as res in 
line 7, where the type is determined by the signature of test (you could 
also write `null (res :: [(Bool,String)])' in line 4, but that would lead 
to
*** Exception: Prelude.head: empty list
for some inputs).

Turning the monomorphism restriction off says explicitly 'let res be a 
polymorphic value', so you get the ambiguous type variable in line 4.

The monomorphism restriction says 'don't generalise the type of res 
[there's no type signature on res, so it's in a restricted binding group]'.
So you get `res :: Read b => [(b,String)]' for some so far unknown, but 
monomorphic b. The use of res in line 7 determines b (here Int, in general 
the same type that instantiates the `a' in test's signature).



More information about the Beginners mailing list