module Data.RangeMin.Fusion.Stream where

import qualified Data.RangeMin.Fusion.Stream.Monadic as SM
import Data.Vector.Fusion.Util

type Stream = SM.Stream Id
type MStream = SM.Stream

{-# INLINE length #-}
length :: Stream a -> Int
length = SM.length

{-# INLINE liftStream #-}
liftStream :: Monad m => Stream a -> SM.Stream m a
liftStream (SM.Stream suc s0 n) = SM.Stream (\ i a -> return (unId (suc i a))) s0 n

{-# INLINE imap #-}
imap :: (Int -> a -> b) -> Stream a -> Stream b
imap = SM.imap

{-# INLINE map #-}
map :: (a -> b) -> Stream a -> Stream b
map = SM.map

{-# INLINE replicate #-}
replicate :: Int -> a -> Stream a
replicate = SM.replicate

{-# INLINE enumN #-}
enumN :: Int -> Stream Int
enumN = SM.enumN

{-# INLINE enumNR #-}
enumNR :: Int -> Stream Int
enumNR = SM.enumNR

{-# INLINE generate #-}
generate :: Int -> (Int -> a) -> Stream a
generate = SM.generate

{-# INLINE iunfoldN #-}
iunfoldN :: Int -> (Int -> b -> Maybe (a, b)) -> b -> Stream a
iunfoldN = SM.iunfoldN

{-# INLINE unfoldN #-}
unfoldN :: Int -> (b -> Maybe (a, b)) -> b -> Stream a
unfoldN = SM.unfoldN

{-# INLINE imapM #-}
imapM :: Monad m => (Int -> a -> m b) -> Stream a -> SM.Stream m b
imapM f = SM.imapM f . liftStream

{-# INLINE mapM #-}
mapM :: Monad m => (a -> m b) -> Stream a -> SM.Stream m b
mapM = imapM . const

{-# INLINE imapM_ #-}
imapM_ :: Monad m => (Int -> a -> m b) -> Stream a -> m ()
imapM_ f = SM.imapM_ f . liftStream

{-# INLINE mapM_ #-}
mapM_ :: Monad m => (a -> m b) -> Stream a -> m ()
mapM_ = imapM_ . const

{-# INLINE snoc #-}
snoc :: Stream a -> a -> Stream a
snoc = SM.snoc

{-# INLINE izipWith #-}
izipWith :: (Int -> a -> b -> c) -> Stream a -> Stream b -> Stream c
izipWith = SM.izipWith

{-# INLINE zipWith #-}
zipWith :: (a -> b -> c) -> Stream a -> Stream b -> Stream c
zipWith = SM.zipWith

{-# INLINE imapAccumL #-}
imapAccumL :: (b -> Int -> a -> (c, b)) -> b -> Stream a -> Stream c
imapAccumL = SM.imapAccumL

{-# INLINE mapAccumL #-}
mapAccumL :: (b -> a -> (c, b)) -> b -> Stream a -> Stream c
mapAccumL = SM.mapAccumL

{-# INLINE iterateN #-}
iterateN :: Int -> a -> (a -> a) -> Stream a
iterateN = SM.iterateN

{-# INLINE ipostscanl #-}
ipostscanl :: (b -> Int -> a -> b) -> b -> Stream a -> Stream b
ipostscanl = SM.ipostscanl

{-# INLINE postscanl #-}
postscanl :: (b -> a -> b) -> b -> Stream a -> Stream b
postscanl = SM.postscanl

{-# INLINE ifoldl #-}
ifoldl :: (b -> Int -> a -> b) -> b -> Stream a -> b
ifoldl f z s = unId (SM.ifoldl f z s)

{-# INLINE foldl #-}
foldl :: (b -> a -> b) -> b -> Stream a -> b
foldl f z s = unId (SM.foldl f z s)

{-# INLINE unbox #-}
unbox :: Stream (Box a) -> Stream a
unbox = SM.unbox

{-# INLINE fromListN #-}
fromListN :: Int -> [a] -> Stream a
fromListN = SM.fromListN