-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Fast loops (for when GHC can't optimize forM_)
--   
--   This package provides a convenient and fast alternative to the common
--   `forM_ [1..n]` idiom, which in many cases GHC cannot fuse to efficient
--   code.
--   
--   See <a>https://ghc.haskell.org/trac/ghc/ticket/8763</a>.
@package loop
@version 0.3.0


-- | Provides a convenient and fast alternative to the common <tt>forM_
--   [1..n]</tt> idiom, which in many cases GHC cannot fuse to efficient
--   code.
--   
--   Notes on fast iteration:
--   
--   <ul>
--   <li>For <a>Int</a>, <tt>(+1)</tt> is almost twice as fast as
--   <a>succ</a> because <a>succ</a> does an overflow check.</li>
--   <li>For <a>Int</a>, you can get around that while still using
--   <a>Enum</a> using <tt>toEnum . (+ 1) . fromEnum</tt>.</li>
--   <li>However, <tt>toEnum . (+ 1) . fromEnum</tt> is slower than
--   <a>succ</a> for <tt>Word32</tt> on 64-bit machines since <a>toEnum</a>
--   has to check if the given <a>Int</a> exceeds 32 bits.</li>
--   <li>Using <tt>(+1)</tt> from <a>Num</a> is always the fastest way, but
--   it gives no overflow checking.</li>
--   <li>Using <a>forLoop</a> you can flexibly pick the way of increasing
--   the value that best fits your needs.</li>
--   <li>The currently recommended replacement for <tt>forM_ [1..n]</tt> is
--   <tt>forLoop 1 (&lt;= n) (+1)</tt>.</li>
--   </ul>
module Control.Loop

-- | <tt>forLoop start cond inc f</tt>: A C-style for loop with starting
--   value, loop condition and incrementor.
forLoop :: Monad m => a -> (a -> Bool) -> (a -> a) -> (a -> m ()) -> m ()

-- | <tt>forLoopState start cond inc initialState f</tt>: A C-style for
--   loop with starting value, loop condition, incrementor and a state that
--   is threaded through the computation.
forLoopState :: Monad m => a -> (a -> Bool) -> (a -> a) -> b -> (b -> a -> m b) -> m b

-- | <tt>forLoopFold start cond inc acc0 f</tt>: A pure fold using a for
--   loop instead of a list for performance.
--   
--   Care is taken that <tt>acc0</tt> not be strictly evaluated if unless
--   done so by <tt>f</tt>.
forLoopFold :: a -> (a -> Bool) -> (a -> a) -> acc -> (acc -> a -> acc) -> acc

-- | <tt>numLoop start end f</tt>: Loops over a contiguous numerical range,
--   including <tt>end</tt>.
--   
--   Does nothing when not <tt>start &lt;= end</tt>.
--   
--   It uses <tt>(+ 1)</tt> so for most integer types it has no bounds
--   (overflow) check.
numLoop :: (Num a, Ord a, Monad m) => a -> a -> (a -> m ()) -> m ()

-- | <tt>numLoopState start end f initialState</tt>: Loops over a
--   contiguous numerical range, including <tt>end</tt> threading a state
--   through the computation.
--   
--   It uses <tt>(+ 1)</tt> so for most integer types it has no bounds
--   (overflow) check.
numLoopState :: (Num a, Eq a, Monad m) => a -> a -> b -> (b -> a -> m b) -> m b

-- | <tt>numLoopFold start end acc0 f</tt>: A pure fold over a contiguous
--   numerical range, including <tt>end</tt>.
--   
--   It uses <tt>(+ 1)</tt> so for most integer types it has no bounds
--   (overflow) check.
--   
--   Care is taken that <tt>acc0</tt> not be strictly evaluated if unless
--   done so by <tt>f</tt>.
numLoopFold :: (Num a, Eq a) => a -> a -> acc -> (acc -> a -> acc) -> acc


-- | This is for trying out loop alternatives.
--   
--   Names and types are subjects to change.
module Control.Loop.Internal

-- | <tt>loop start end f</tt>: Loops from <tt>start</tt> to <tt>end</tt>
--   (inclusive), executing <tt>f</tt> on each iteration. Same as <tt>forM_
--   [start..end] f</tt>.
--   
--   Uses <a>succ</a> inside, which does a bounds (overflow) check.
loop :: (Enum e, Eq e, Monad m) => e -> e -> (e -> m ()) -> m ()

-- | Like <a>loop</a>, but (sometimes) without bounds (overflow) check.
--   
--   This circumvents the implementation of <a>succ</a> for the
--   <tt>Enum</tt> type and uses <tt>toEnum . (+ 1) . fromEnum</tt>
--   instead, so it will break on Enums that are not contiguous.
--   
--   Note that some types (e.g. Word32) have bounds checks even for
--   <a>toEnum</a>.
unsafeLoop :: (Enum e, Eq e, Monad m) => e -> e -> (e -> m ()) -> m ()
