Haskell pattern matching too strict?

Malcolm Wallace Malcolm.Wallace at cs.york.ac.uk
Tue Jan 9 09:34:11 EST 2001


> -- broken fragment
> instance (Typeable a, Typeable b) => Typeable (a,b) where
>   typeOf (x,y) = "("++(typeOf x)++ ","++(typeOf y)++")"
> --

> Is this too strict? It never uses the tuple or its arguments yet
> tries to construct the tuple anyway.

Yes, this is too strict, but no, Haskell is correctly doing what you
asked for here.  When you write

    f (x,y) = ...

the pattern must be matched before the system can decide which clause
of the function definition to commit to.  Hence, it must evaluate
the tuple as far as the (,) constructor, to be sure that it actually
has one.

If you really don't want to construct the tuple at all, then you
mustn't match on it strictly.  There are many ways to make the
match non-strict - in all cases, you must defer the pattern-match
to the rhs of the equation, i.e. after the system has determined
which equation clause to use.

    f ~(x,y) = ...

    f xy = ... where (x,y) = xy

    f xy = let (x,y) = xy in ...

By a similar trick, you can improve this:

> instance Typeable a => Typeable [a] where
>   typeOf x = "["++(typeOf (see x))++"]"
>     where
>       see :: [a] -> a
>       see = undefined 

to be simpler:

  instance Typeable a => Typeable [a] where
    typeOf xs = "["++(typeOf x)++"]"
      where (x:_) = xs

Regards,
    Malcolm




More information about the Glasgow-haskell-bugs mailing list