13

Repeat is defined as follows:

repeat :: a -> [a]
repeat x = xs where xs = x:xs

Is there any reason that the following isn't used?

repeat :: a -> [a]
repeat x = x : repeat x

(Obviously there are many equivalent definitions for many Prelude functions, but my latter description just feels much more obvious. I wonder if there's a performance or style reason for the way it is.)

8128
  • 880
  • 1
  • 7
  • 23
  • 6
    [See my answer here](http://stackoverflow.com/questions/16632143/why-recursive-let-make-space-effcient/16632403#16632403). The definition there uses `let`, but it's the same behavior with `where`. – hammar Jun 10 '13 at 20:14

1 Answers1

20

It is for performance and space complexity reasons.

The first version of the code uses explicit sharing; it basically looks like a one-element circular linked list in memory (the xs in the code is a list node that has x as value and its tail points to the very same list node). When you evaluate more and more elements of the list it will just take the same node repeatedly.

In contrast, the second version creates a list that actually grows in memory as it is evaluated, because different invocations of repeat x are always recomputed (and not memoized). There will be always yet another unevaluated thunk at end of the generated list.

András Kovács
  • 29,038
  • 3
  • 45
  • 94