Adrian Hey writes:

> Consider the following function..

> demo1 :: (a -> b) -> Either a c -> Either b c
> demo1 f (Left  a) = Left (f a)
> demo1 _ (Right c) = Right c

> My first question is, can programmers safely assume that the
> compiler is sufficiently smart to avoid duplicating the expression
> (Right c) in the event that the second match above succeeds? 

> One might reasonably hope that the run time implementation of this
> function will simply return the functions second argument in this
> case.

Sadly I don't think one can assume this at all, and for a fairly
good reason.  The argument (Right c :: Either a c) and the result
(Right c :: Either b c) need not have the same runtime
representation.  In a strict language like ML, for example, we might
well have

        sizeof (Either a c) = sizeof tag + max (sizeof a, sizeof c)

        sizeof (Either b c) = sizeof tag + max (sizeof b, sizeof c)

and there is no reason for these to be the same.  Obviously
non-strictness can change things a bit, but the situation isn't
going to be any better.

If a compiler is specialising polymorphic functions, it might pick
up that an actual use of demo1 can be done more simply, but this is
about all one can hope for.  The point is that `demo1' genuinely is
mildly non-trivial to code in some situations.  Haskell makes it
smooth for you to write, which is good, but it can't make the
underlying problem go away altogether.

I have to admit I was a bit taken aback by this, but I think it is
an instance of polymorphism and overloading being just so convenient
you forget that they are there: those two uses of `Right' look so
much, well, the same.

Ian Stark

.....................................................................
Ian Stark                          http://www.dcs.ed.ac.uk/home/stark
Department of Computer Science, The University of Edinburgh, Scotland


Reply via email to