module Data.Stream
( Stream
, mkStream
, head
, tail
, cons
, elemAt
, toSeq
, toList
, mapStreamSt
, fibs
) where
import Prelude hiding (head, tail, drop)
import Control.Comonad
import Control.Arrow ((&&&))
data Stream a = forall b. S b (b -> a) (b -> b)
mkStream :: b -> (b -> a) -> (b -> b) -> Stream a
mkStream x f g = S x f g
instance Functor Stream where
fmap = liftW
instance Comonad Stream where
extract (S s f _) = f s
extend h (S s f g) = S s (\s' -> h (S s' f g)) g
head :: Stream a -> a
head (S x f _) = f x
tail :: Stream a -> Stream a
tail (S x f g) = S (g x) f g
cons :: a -> Stream a -> Stream a
cons x s = mkStream (x,s) fst ((head &&& tail) . snd)
elemAt :: Integral i => i -> Stream a -> a
elemAt n = head . drop n
drop :: Integral i => i -> Stream a -> Stream a
drop 0 = id
drop n = drop (n 1) . tail
toSeq :: Stream a -> Int -> a
toSeq = flip elemAt
toList :: Stream a -> [a]
toList = map head . iterate tail
mapStreamSt :: (a -> s -> b) -> (a -> s -> s) -> s -> Stream a -> Stream b
mapStreamSt f1 f2 s0 xs
= mkStream (xs,s0)
(\(x,s) -> f1 (head x) s)
(\(x,s) -> (tail x, f2 (head x) s))
fibs :: Stream Integer
fibs = mkStream (1,1) fst (\(i,j) -> (j,i+j))