Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell need help understanding stream

I have this code where these functions have been made:

  1. creates an infinite list out of the given stream;
  2. creates a stream for the given iteration function and the starting stream element (seed);
  3. merges two streams into one so that their elements are interleaved.

The code is as follows:

data Stream a = Cons a (Stream a)

streamToList :: Stream a -> [a]
streamToList (Cons x xs) = x : streamToList xs

streamIterate :: (a -> a) -> a -> Stream a
streamIterate f x = Cons x (streamIterate f (f x))

streamIterLeave :: Stream a -> Stream a -> Stream a
streamIterLeave (Cons x xs) ys = Cons x (streamIterLeave ys xs)

Now what I am having problems with is I have no idea how to check this code on ghci. To be more specific, how do I input a stream into the command line?

For example I tried streamToList [1,2,3] ; streamToList (1,2,3); streamToList 1,2,3 and none of them seem to be working.

Help is very much appreciated!

like image 993
Quin Avatar asked Feb 25 '26 04:02

Quin


1 Answers

Several ways. The simplest is just using undefined:

> take 2 $ streamToList $ Cons 1 $ Cons 2 undefined
[1,2]

You can defined named streams at the prompt,

> let { one = Cons 1 two ; two = Cons 2 one } 

or with multi-line input,

> :{
| one = Cons 1 two
| two = Cons 2 one
| :}

> take 5 $ streamToList one
[1,2,1,2,1]

and you can use your streamIterate as shown in the comments or use foldr to create your streams from lists,

> take 5 $ streamToList $ streamIterate (+1) 0
[0,1,2,3,4]
> listToStream xs = foldr Cons undefined xs
> intS = listToStream [1..]
> take 5 $ streamToList intS 
[1,2,3,4,5]

Having defined listToStream you can further easily define

> mapStream f s = listToStream . map f . streamToList $ s
> intsStream = x where { x = Cons 1 $ mapStream (1+) x }
> take 5 $ streamToList intsStream
[1,2,3,4,5]
> zipStr s1 s2 = listToStream $ zip (streamToList s1) (streamToList s2)
> zipStrWith f s1 s2 = mapStream (uncurry f) (zipStr s1 s2)
> addStreams s1 s2 = zipStrWith (+) s1 s2
> fibS = let {a = Cons 0 b; b = Cons 1 c; c = addStreams a b} in a
> take 15 $ streamToList fibS
[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]

etc. etc. etc.


as dfeuer mentions in the comments, listToStream above is a bit bogus -- it allows for invalid (i.e. finite) lists as its argument. It's OK for playing with it at the REPL, but not in general.

It could be better to "pull the bogosity out to the call site", by defining

> :{ 
| (+++) :: [a] -> Stream a -> Stream a
| xs +++ ys  =  foldr Cons ys xs
| :}

allowing us to define streams like

> good = [1..] +++ undefined
> bad = [1..10] +++ undefined

where the problem, if present, is more immediately apparent.

like image 186
Will Ness Avatar answered Feb 28 '26 03:02

Will Ness



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!