import "JavaBuiltin" as Java data Either a b = Left a | Right b data Stream a = Stream (s -> Step a s) s data Step a s = Done | Yield a s | Skip s // stream :: [a] -> Stream a // unstream :: Stream a -> [a] // streamRev :: [a] -> Stream a // unstreamRev :: Stream a -> [a] //toStream :: [a] -> Stream a //toStream l = Stream (\i -> if i >= length l then Done else Yield (get l i) (i+1)) 0 filterS :: (a -> Boolean) -> Stream a -> Stream a filterS p (Stream next0 s0) = Stream next s0 where next s = match next s with Done -> Done Skip s -> Skip s Yield a s -> if p a then Yield a s else Skip s mapS :: (a -> b) -> Stream a -> Stream b mapS f (Stream next0 s0) = Stream next s0 where next s = match next0 s with Done -> Done Skip s -> Skip s Yield a s -> Yield (f a) s appendS :: Stream a -> Stream a -> Stream a appendS (Stream next1 s1) (Stream next2 s2) = Stream next (Left s1) where next (Left s) = match next1 s with Done -> Skip (Right s2) Skip s -> Skip (Left s) Yield a s -> Yield a (Left s) next (Right s) = match next2 s with Done -> Done Skip s -> Skip (Right s) Yield a s -> Yield a (Right s) decomposeS :: Stream a -> Maybe (a, Stream a) decomposeS (Stream next s0) = loop s0 where loop s = match next s with Done -> Nothing Skip s -> loop s Yield a s -> Just (a, Stream next s) returnS :: a -> Stream a returnS x = Stream next True where next True = Yield x False next False = Done isEmptyS :: Stream a -> Boolean isEmptyS (Stream next s0) = loop s0 where loop s = match next s with Done -> True Skip s -> loop s Yield _ _ -> False foldlS :: (a -> b -> a) -> a -> Stream b -> a foldlS f init (Stream next s0) = go init s0 where go cur s = match next s with Done -> cur Skip s -> go cur s Yield x s -> go (f cur x) s scanlS :: (a -> b -> a) -> a -> Stream b -> Stream a scanlS f init (Stream next0 s0) = Stream next (s0, init) where next (s,v) = match next0 s with Done -> Done Skip s -> Skip (s, v) Yield x s -> Yield v (s, f v x) concatMapS :: (a -> Stream b) -> Stream a -> Stream b concatMapS f (Stream next0 s0) = Stream next (s0, Nothing) where next (s, Nothing) = match next0 s with Done -> Done Skip s -> Skip (s, Nothing) Yield x s -> Skip (s, Just (f x)) next (s0, Just (Stream next1 s1)) = match next1 s1 with Done -> Skip (s0, Nothing) Skip s -> Skip (s0, Just (Stream next1 s)) Yield x s -> Yield x (s0, Just (Stream next1 s)) zipWithS :: (a -> b -> c) -> Stream a -> Stream b -> Stream c zipWithS f (Stream next0 s0) (Stream next1 s1) = Stream next (s0, s1, Nothing) where next (s0, s1, Nothing) = match next0 s0 with Done -> Done Skip s -> Skip (s, s1, Nothing) Yield x s -> Skip (s, s1, Just x) next (s0, s1, Just x) = match next1 s1 with Done -> Done Skip s -> Skip (s0, s, Just x) Yield y s -> Yield (f x y) (s0, s, Nothing) guardS :: Boolean -> Stream a -> Stream a guardS b (Stream next0 s0) = Stream next (b, s0) where next (False, _) = Done next (True, s) = match next0 s with Done -> Done Skip s -> Skip (True, s) Yield x s -> Yield x (True, s) /* takeS :: Integer -> Stream a -> Stream a takeS count (Stream next0 s0) = Stream next (count, s0) where next (count, s) = if count <= 0 then Done else match next0 s with Done -> Done | Skip s -> Skip (count, s) | Yield x s -> Yield x (count, s) */ repeatS :: a -> Stream a repeatS v = Stream next () where next () = Yield v () iterateS :: (a -> a) -> a -> Stream a iterateS f v = Stream next v where next v = Yield v (f v) main :: Integer main = foldlS Java.iadd (0 :: Integer) (appendS (appendS (returnS (1 :: Integer)) (returnS (2 :: Integer))) (returnS (3 :: Integer))) -- 6