{-# LANGUAGE BangPatterns #-}
module Control.Loop
( forLoop
, forLoopState
, forLoopFold
, numLoop
, numLoopState
, numLoopFold
) where
forLoop :: (Monad m) => a -> (a -> Bool) -> (a -> a) -> (a -> m ()) -> m ()
forLoop :: a -> (a -> Bool) -> (a -> a) -> (a -> m ()) -> m ()
forLoop a
start a -> Bool
cond a -> a
inc a -> m ()
f = a -> m ()
go a
start
where
go :: a -> m ()
go !a
x | a -> Bool
cond a
x = a -> m ()
f a
x m () -> m () -> m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> a -> m ()
go (a -> a
inc a
x)
| Bool
otherwise = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
{-# INLINE forLoop #-}
forLoopState :: (Monad m) => a -> (a -> Bool) -> (a -> a) -> b -> (b -> a -> m b) -> m b
forLoopState :: a -> (a -> Bool) -> (a -> a) -> b -> (b -> a -> m b) -> m b
forLoopState a
start a -> Bool
cond a -> a
inc b
initialState b -> a -> m b
f = a -> b -> m b
go a
start b
initialState
where
go :: a -> b -> m b
go !a
x !b
state | a -> Bool
cond a
x = b -> a -> m b
f b
state a
x m b -> (b -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> b -> m b
go (a -> a
inc a
x)
| Bool
otherwise = b -> m b
forall (m :: * -> *) a. Monad m => a -> m a
return b
state
{-# INLINE forLoopState #-}
forLoopFold :: a -> (a -> Bool) -> (a -> a) -> acc -> (acc -> a -> acc) -> acc
forLoopFold :: a -> (a -> Bool) -> (a -> a) -> acc -> (acc -> a -> acc) -> acc
forLoopFold a
start a -> Bool
cond a -> a
inc acc
acc0 acc -> a -> acc
f = acc -> a -> acc
go acc
acc0 a
start
where
go :: acc -> a -> acc
go acc
acc !a
x | a -> Bool
cond a
x = let acc' :: acc
acc' = acc -> a -> acc
f acc
acc a
x
in acc
acc' acc -> acc -> acc
`seq` acc -> a -> acc
go acc
acc' (a -> a
inc a
x)
| Bool
otherwise = acc
acc
{-# INLINE forLoopFold #-}
numLoop :: (Num a, Ord a, Monad m) => a -> a -> (a -> m ()) -> m ()
numLoop :: a -> a -> (a -> m ()) -> m ()
numLoop a
start a
end a -> m ()
f = if a
start a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
end then a -> m ()
go a
start else () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where
go :: a -> m ()
go !a
x | a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
end = a -> m ()
f a
x
| Bool
otherwise = a -> m ()
f a
x m () -> m () -> m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> a -> m ()
go (a
xa -> a -> a
forall a. Num a => a -> a -> a
+a
1)
{-# INLINE numLoop #-}
numLoopState :: (Num a, Eq a, Monad m) => a -> a -> b -> (b -> a -> m b) -> m b
numLoopState :: a -> a -> b -> (b -> a -> m b) -> m b
numLoopState a
start a
end b
initState b -> a -> m b
f = a -> b -> m b
go a
start b
initState
where
go :: a -> b -> m b
go !a
x !b
state | a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
end = b -> a -> m b
f b
state a
x
| Bool
otherwise = b -> a -> m b
f b
state a
x m b -> (b -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> b -> m b
go (a
xa -> a -> a
forall a. Num a => a -> a -> a
+a
1)
{-# INLINE numLoopState #-}
numLoopFold :: (Num a, Eq a) => a -> a -> acc -> (acc -> a -> acc) -> acc
numLoopFold :: a -> a -> acc -> (acc -> a -> acc) -> acc
numLoopFold a
start a
end acc
acc0 acc -> a -> acc
f = acc -> a -> acc
go acc
acc0 a
start
where
go :: acc -> a -> acc
go acc
acc !a
x | a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
end = acc -> a -> acc
f acc
acc a
x
| Bool
otherwise = let acc' :: acc
acc' = acc -> a -> acc
f acc
acc a
x
in acc
acc' acc -> acc -> acc
`seq` acc -> a -> acc
go acc
acc' (a
xa -> a -> a
forall a. Num a => a -> a -> a
+a
1)
{-# INLINE numLoopFold #-}