hw-streams-0.0.0.7: src/HaskellWorks/Data/Streams/Stream.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module HaskellWorks.Data.Streams.Stream where
import Data.Bool
import HaskellWorks.Data.Streams.Size
import Prelude hiding (drop, zipWith)
data Stream a where
Stream :: ()
=> (s -> Step s a)
-> s
-> Size
-> Stream a
instance Functor Stream where
fmap f (Stream step s i) = Stream (fmap f <$> step) s i
{-# INLINE fmap #-}
data Step s a
= Yield a s
| Skip s
| Done
instance Functor (Step s) where
fmap f (Yield a s) = Yield (f a) s
fmap _ (Skip s) = Skip s
fmap _ Done = Done
{-# INLINE fmap #-}
zipWith :: (a -> b -> c) -> Stream a -> Stream b -> Stream c
zipWith f (Stream stepa sa na) (Stream stepb sb nb) = Stream step (sa, sb, Nothing) (smaller na nb)
where step (ta, tb, Nothing) = case stepa ta of
Yield xa ta0 -> Skip (ta0, tb, Just xa)
Skip ta0 -> Skip (ta0, tb, Nothing)
Done -> Done
step (ta, tb, Just xa) = case stepb tb of
Yield y tb0 -> Yield (f xa y) (ta, tb0, Nothing)
Skip tb0 -> Skip (ta, tb0, Just xa)
Done -> Done
{-# INLINE [0] step #-}
{-# INLINE [1] zipWith #-}
zipWithState :: (a -> b -> s -> (c, s)) -> s -> Stream a -> Stream b -> Stream c
zipWithState f state (Stream stepa sa na) (Stream stepb sb nb) = Stream step (sa, sb, Nothing, state) (smaller na nb)
where step (ta, tb, Nothing, oldState) = case stepa ta of
Yield xa ta0 -> Skip (ta0, tb, Just xa, oldState)
Skip ta0 -> Skip (ta0, tb, Nothing, oldState)
Done -> Done
step (ta, tb, Just xa, oldState) = case stepb tb of
Yield y tb0 -> let (newValue, newState) = f xa y oldState in Yield newValue (ta, tb0, Nothing, newState)
Skip tb0 -> Skip (ta, tb0, Just xa, oldState)
Done -> Done
{-# INLINE [0] step #-}
{-# INLINE [1] zipWithState #-}
enumFromStepN :: Num a => a -> a -> Int -> Stream a
enumFromStepN x y n = x `seq` y `seq` n `seq` Stream step (x, n) (Exact n)
where step (w, m) | m > 0 = Yield w (w + y, m - 1)
| otherwise = Done
{-# INLINE [0] step #-}
{-# INLINE [1] enumFromStepN #-}
foldl :: (a -> b -> a) -> a -> Stream b -> a
foldl f z (Stream step s _) = loop z s
where loop za sa = za `seq` case step sa of
Yield x sb -> loop (f za x) sb
Skip sb -> loop za sb
Done -> za
{-# INLINE [1] foldl #-}
drop :: Int -> Stream a -> Stream a
drop n s@(Stream step state size) = if n > 0
then case step state of
Yield _ newState -> drop (n - 1) $ Stream step newState (size - 1)
Skip newState -> drop n $ Stream step newState size
Done -> s
else s
{-# RULES
"zipWith xs xs [Vector.Stream]" forall f xs. zipWith f xs xs = fmap (\x -> f x x) xs #-}
append :: Stream a -> Stream a -> Stream a
append (Stream stepa ta na) (Stream stepb tb nb) = Stream step (Left ta) (na + nb)
where step (Left sa) = case stepa sa of
Yield x sa' -> Yield x (Left sa')
Skip sa' -> Skip (Left sa')
Done -> Skip (Right tb)
step (Right sb) = case stepb sb of
Yield x sb' -> Yield x (Right sb')
Skip sb' -> Skip (Right sb')
Done -> Done
{-# INLINE step #-}
{-# INLINE append #-}
singleton :: a -> Stream a
singleton a = Stream (bool Done (Yield a False)) True 1
repeat :: Int -> a -> Stream a
repeat n a = Stream step n 1
where step i = if i > 0 then Yield a (i - 1) else Done
transcribe :: (s -> a -> (b, s)) -> s -> Stream a -> Stream b
transcribe f w (Stream step state size) = Stream step' (state, w) size
where step' (t, x) = case step t of
Yield a s' -> let (z, y) = f x a in Yield z (s', y)
Skip s' -> Skip (s', x)
Done -> Done
{-# INLINE step' #-}
{-# INLINE transcribe #-}
concatMap :: (a -> Stream b) -> Stream a -> Stream b
concatMap f (Stream stepA stateA _) = Stream stepC (stateA, Nothing) Unknown
where stepC (stateA0, Nothing) = case stepA stateA0 of
Yield a stateA1 -> Skip (stateA1, Just (f a))
Skip stateA1 -> Skip (stateA1, Nothing)
Done -> Done
stepC (stateA0, Just (Stream stepB stateB _)) = case stepB stateB of
Yield b stateB1 -> Yield b (stateA0, Just (Stream stepB stateB1 Unknown))
Skip stateB1 -> Skip (stateA0, Just (Stream stepB stateB1 Unknown))
Done -> Skip (stateA0, Nothing)
{-# INLINE concatMap #-}
dupMap :: forall a b. (a -> b) -> (a -> b) -> Stream a -> Stream b
dupMap f g (Stream stepA stateA _) = Stream (mkStepB stepA) (stateA, Nothing) Unknown
where mkStepB :: (s -> Step s a) -> (s, Maybe b) -> Step (s, Maybe b) b
mkStepB step (s, mw) = case mw of
Nothing -> case step s of
Yield a t -> Yield (f a) (t, Just (g a))
Skip t -> Skip (t, Nothing)
Done -> Done
Just w -> Yield w (s, Nothing)
{-# INLINE dupMap #-}