[Haskell-beginners] Data.Stream interleave implementation question
Isaac Dupree
ml at isaac.cedarswampstudios.org
Wed Feb 12 08:36:41 UTC 2014
On 02/11/2014 11:23 PM, Bryan Brady wrote:
> [...]
> interleaveStreams :: Stream a -> Stream a -> Stream a
> interleaveStreams (Cons a as) (Cons b bs) = Cons a (Cons b
> (interleaveStreams as bs))
>
> ruler :: Stream Integer
> ruler = foldr1 interleaveStreams (map streamRepeat [0..])
> [...]
> In the latter definition, Cons a (interleaveStreams bs as),
> (interleaveStreams bs as) is a thunk. The thunk should only be evaluated
> when it is needed. In my original definition, (interleaveStreams as bs)
> is a thunk. The difference is an extra Cons (e.g., Cons b). It seems
> like the additional Cons is causing problems, I just don't understand
> why. Can anyone point out what I'm missing?
The issue is on the left-hand-side of interleaveStreams. It is strict
in both its arguments. Look at foldr1; you're evaluating
interleaveStreams (streamRepeat 0)
(interleaveStreams (streamRepeat 1)
(interleaveStreams (streamRepeat 2)
(interleaveStreams (streamRepeat 3)
...
In this situation, if interleaveStreams evaluates its second argument
before returning any work, it will never be able to return. Happily,
the outer Cons of the result does not depend on the second argument. I
can fix the issue just by making the second argument be pattern-matched
lazily (with ~, i.e. only as soon as any uses of the argument in the
function are evaluated):
interleaveStreams (Cons a as) ~(Cons b bs) = Cons a (Cons b
(interleaveStreams as bs))
You can also write this without ~ by explicitly pattern matching later, e.g.
interleaveStreams (Cons a as) bs = Cons a (case bs of Cons b bs' -> Cons
b (interleaveStreams as bs'))
I'm not sure whether there's a practical difference between these and
Data.Stream's definition. Actually, I think they turn out to do exactly
the same thing...
(I tested by deriving Show for Stream, and typing 'ruler' in `ghci
file.hs`, or 'take 80 (show ruler)'.)
-Isaac
More information about the Beginners
mailing list