Hi,

Yves Parès wrote:
A question recently popped into my mind: does lazy evaluation reduce the
need to "proper" tail-recursion?
I mean, for instance :

fmap f [] = []
fmap f (x:xs) = f x : fmap f xs

Here fmap is not tail-recursive, but thanks to the fact that operator (:) is
lazy, I think that it may still run in constant space/time, am I right?

In a sense, that definition of fmap is tail-recursive.

To see that, consider how a non-strict list could be encoded in a strict language:

  data EvaluatedList a
    =  Cons a (List a)
    |  Empty

  type List a
    = () -> EvaluatedList a

  map :: (a -> b) -> (List a -> List b)
  map f xs
    = \_ -> case xs () of
              Cons x xs  ->  Cons (f x) (\_ -> map f xs ())
              Empty      ->  Empty

Here, the call to map is more visibly in tail position.


So I would say that in Haskell, tail-call optimization is just as important as, for example, in Scheme. But tail positions are not defined syntactically, but semantically, depending on the strictness properties of the program.

  Tillmann

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to