Just for your fun and horror

Theodore Norvell theo@engr.mun.ca
Tue, 20 Feb 2001 17:49:54 -0330


Some comments in this discussion have said that "return"
is a good name for "return" since it is analogous
to "return" in C (and C++ and fortran and java etc.).
At first I thought "good point", but after
thinking about it a bit, I'd like to argue the contrary.

"return" in Haskell is not analogous to "return" in C.

Obviously the analogy, if there is one, is strongest in
Monads that model imperative effects, like a state monad
or the IO monad, so in the following, I'll assume the
monads involved are of this nature.

First consider this C subroutine:
	int f() {
		const int i = g() ;
		return h(i) ;  // where h may have side effects.
	}
The "return" here serves to indicate the value returned by the
subroutine. In Haskell's do syntax, there is no need for
this sort of "return" because the value delivered by a "do" is the
value delivered by its syntactically last computation, i.e. "return"
in the C sense is entirely implicit.
Haskell:
        f = do i <- g()
               h(i)          // No return
If "return" in Haskell were analogous to "return" in C, we
could write
        f = do i <- g()
               return h(i)
Indeed you can write that (and I sometimes do!), but the
meaning is different; in C executing the "return" executes the
side effects of h(i); in Haskell "executing" the "return" returns
h(i) with its side effects unexecuted.

Now consider Haskell's "return".  In Haskell, for the relevant monads,
"return" promotes a "pure" expression to an "impure" expression
with a side effect; of course the side effect is trivial, but it
is still there.

In C, as others have pointed out, there is, from a language definition
point of view, no distinction between pure and impure expressions,
so there is no need for such a promotion operator; and C does not
have one.  Consider Haskell:
        m = do j <- return e
               n(j)

C:
	void m() {
		const int j = e ;   /* No return */
		n(j) ; }

In C, but not Haskell, "return" has important implications
for flow of control.  Consider C:
        void w() {
            while(a) {
                if( b ) return c ;
                d ;
        }
In Haskell there is no close equivalent (which I say is a good thing).  The closest
analogue is to throw an exception, which is in a sense the opposite of a "return".
If you wrote a denotational semantics of C, you'd find that the denotation
of "return" is very similar to the denotation of "throw".  The implementation
of return is easier, since it is statically nested in its "handler", but this
distinction probably won't show up in the semantics.

In Haskell "return" has no implications for flow of control. Consider Haskell
        x = do y
               return e
               z
In we have C:
        void x() {
            y() ;
            e ;           // semicolon, no return
            z() ; }
The above code is silly, but the point is that if C's "return" were
analogous, we could write
        int x() {
            y() ;
            return e ;
            z() ; }
which is not analogous to the Haskell. This example also shows
another type distinction, since in the Haskell version the type
of e can be anything, yet in the second C version the type of e must
be the same as return type of x().

In short, "return" in C introduces an important side effect
(returning from the function) whereas "return" in any Haskell
monad should introduce only a trivial (identity) side effect.

It could be argued that there is a loose analogy in that
"return" in Haskell converts an expression to a command,
just as "return" in C converts an expression to a command. But
in C, putting a semicolon after an expression also converts
an expression to a command, and as the last example shows,
this is a better analogue since, unlike "return" there are
no additional nontrivial effects introduced.

In summary: (0) There is no analogue, in C, to Haskell's return
because the is no analogue to Haskell's type distinction
between expressions without side effects (pure expressions)
and expressions with side effects. (1) The main point of
"return" in C is to introduce a nontrivial side effect,
and the rule in Haskell is that "return" introduces the
trivial side effect.  The analogue of C's "return" can instead
be built on top of an exception model.

I'm not saying that future Haskells shouldn't call "return"
"return", or that "return" is not a good name for "return",
just that the analogy does not hold up.

Cheers,
Theo Norvell

----------------------------
Dr. Theodore Norvell                                    theo@engr.mun.ca
Electrical and Computer Engineering         http://www.engr.mun.ca/~theo
Engineering and Applied Science                    Phone: (709) 737-8962
Memorial University of Newfoundland                  Fax: (709) 737-4042
St. John's, NF, Canada, A1B 3X5