module DeferredFolds.Defs.UnfoldlM
where
import DeferredFolds.Prelude hiding (mapM_, foldM)
import DeferredFolds.Types
import qualified DeferredFolds.Prelude as A
import qualified Data.ByteString.Internal as ByteString
import qualified Data.ByteString.Short.Internal as ShortByteString
deriving instance Functor m => Functor (UnfoldlM m)
instance Monad m => Applicative (UnfoldlM m) where
pure x =
UnfoldlM (\ step init -> step init x)
(<*>) = ap
instance Monad m => Alternative (UnfoldlM m) where
empty =
UnfoldlM (const return)
{-# INLINE (<|>) #-}
(<|>) (UnfoldlM left) (UnfoldlM right) =
UnfoldlM (\ step init -> left step init >>= right step)
instance Monad m => Monad (UnfoldlM m) where
return = pure
{-# INLINE (>>=) #-}
(>>=) (UnfoldlM left) rightK =
UnfoldlM $ \ step init ->
let
newStep output x =
case rightK x of
UnfoldlM right ->
right step output
in left newStep init
instance Monad m => MonadPlus (UnfoldlM m) where
mzero = empty
mplus = (<|>)
instance MonadTrans UnfoldlM where
lift m = UnfoldlM (\ step init -> m >>= step init)
instance Monad m => Semigroup (UnfoldlM m a) where
(<>) = (<|>)
instance Monad m => Monoid (UnfoldlM m a) where
mempty = empty
mappend = (<>)
instance Foldable (UnfoldlM Identity) where
{-# INLINE foldMap #-}
foldMap inputMonoid = foldl' step mempty where
step monoid input = mappend monoid (inputMonoid input)
foldl = foldl'
{-# INLINE foldl' #-}
foldl' step init (UnfoldlM run) =
runIdentity (run identityStep init)
where
identityStep state input = return (step state input)
instance Eq a => Eq (UnfoldlM Identity a) where
(==) left right = toList left == toList right
instance Show a => Show (UnfoldlM Identity a) where
show = show . toList
instance IsList (UnfoldlM Identity a) where
type Item (UnfoldlM Identity a) = a
fromList list = foldable list
toList = foldr (:) []
{-# INLINE null #-}
null :: Monad m => UnfoldlM m input -> m Bool
null (UnfoldlM run) = run (\ _ _ -> return False) True
{-# INLINE foldlM' #-}
foldlM' :: Monad m => (output -> input -> m output) -> output -> UnfoldlM m input -> m output
foldlM' step init (UnfoldlM run) =
run step init
{-# INLINE mapM_ #-}
mapM_ :: Monad m => (input -> m ()) -> UnfoldlM m input -> m ()
mapM_ step = foldlM' (const step) ()
{-# INLINE forM_ #-}
forM_ :: Monad m => UnfoldlM m input -> (input -> m ()) -> m ()
forM_ = flip mapM_
{-# INLINE fold #-}
fold :: Fold input output -> UnfoldlM Identity input -> output
fold (Fold step init extract) = extract . foldl' step init
{-# INLINE foldM #-}
foldM :: Monad m => FoldM m input output -> UnfoldlM m input -> m output
foldM (FoldM step init extract) view =
do
initialState <- init
finalState <- foldlM' step initialState view
extract finalState
{-# INLINE mapFoldMInput #-}
mapFoldMInput :: Monad m => (forall x. FoldM m b x -> FoldM m a x) -> UnfoldlM m a -> UnfoldlM m b
mapFoldMInput newFoldM unfoldM = UnfoldlM $ \ step init -> foldM (newFoldM (FoldM step (return init) return)) unfoldM
{-# INLINE foldable #-}
foldable :: (Monad m, Foldable foldable) => foldable a -> UnfoldlM m a
foldable foldable = UnfoldlM (\ step init -> A.foldlM step init foldable)
{-# INLINE foldlRunner #-}
foldlRunner :: Monad m => (forall x. (x -> a -> x) -> x -> x) -> UnfoldlM m a
foldlRunner run = UnfoldlM (\ stepM state -> run (\ stateM a -> stateM >>= \state -> stepM state a) (return state))
{-# INLINE foldrRunner #-}
foldrRunner :: Monad m => (forall x. (a -> x -> x) -> x -> x) -> UnfoldlM m a
foldrRunner run = UnfoldlM (\ stepM -> run (\ x k z -> stepM z x >>= k) return)
unfoldr :: Monad m => Unfoldr a -> UnfoldlM m a
unfoldr (Unfoldr unfoldr) = foldrRunner unfoldr
{-# INLINE filter #-}
filter :: Monad m => (a -> m Bool) -> UnfoldlM m a -> UnfoldlM m a
filter test (UnfoldlM run) = UnfoldlM (\ step -> run (\ state element -> test element >>= bool (return state) (step state element)))
{-# INLINE intsInRange #-}
intsInRange :: Monad m => Int -> Int -> UnfoldlM m Int
intsInRange from to =
UnfoldlM $ \ step init ->
let
loop !state int =
if int <= to
then do
newState <- step state int
loop newState (succ int)
else return state
in loop init from
{-# INLINE tVarValue #-}
tVarValue :: TVar a -> UnfoldlM STM a
tVarValue var = UnfoldlM $ \ step state -> do
a <- readTVar var
step state a
{-# INLINE hoist #-}
hoist :: (forall a. m a -> n a) -> (forall a. n a -> m a) -> UnfoldlM m a -> UnfoldlM n a
hoist trans1 trans2 (UnfoldlM unfold) = UnfoldlM $ \ step init ->
trans1 (unfold (\ a b -> trans2 (step a b)) init)
{-# INLINABLE byteStringBytes #-}
byteStringBytes :: ByteString -> UnfoldlM IO Word8
byteStringBytes (ByteString.PS fp off len) =
UnfoldlM $ \ step init ->
withForeignPtr fp $ \ ptr ->
let
endPtr = plusPtr ptr (off + len)
iterate !state !ptr = if ptr == endPtr
then return state
else do
x <- peek ptr
newState <- step state x
iterate newState (plusPtr ptr 1)
in iterate init (plusPtr ptr off)
{-# INLINE shortByteStringBytes #-}
shortByteStringBytes :: Monad m => ShortByteString -> UnfoldlM m Word8
shortByteStringBytes (ShortByteString.SBS ba#) = primArray (PrimArray ba#)
{-# INLINE primArray #-}
primArray :: (Monad m, Prim prim) => PrimArray prim -> UnfoldlM m prim
primArray pa = UnfoldlM $ \ f z -> foldlPrimArrayM' f z pa
{-# INLINE primArrayWithIndices #-}
primArrayWithIndices :: (Monad m, Prim prim) => PrimArray prim -> UnfoldlM m (Int, prim)
primArrayWithIndices pa = UnfoldlM $ \ step state -> let
!size = sizeofPrimArray pa
iterate index !state = if index < size
then do
newState <- step state (index, indexPrimArray pa index)
iterate (succ index) newState
else return state
in iterate 0 state