-- | Common 'Control.Monad' variations.
module Sound.Sc3.Common.Monad where

-- | 'sequence' of 'repeat'
repeatM :: Monad m => m t -> m [t]
repeatM :: forall (m :: * -> *) t. Monad m => m t -> m [t]
repeatM = forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> [a]
repeat

-- | This is the same function as Control.Monad.void, which however hugs does not know of.
mvoid :: Monad m => m a -> m ()
mvoid :: forall (m :: * -> *) a. Monad m => m a -> m ()
mvoid m a
f = m a
f forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- | 'void' of 'repeatM'.
repeatM_ :: Monad m => m t -> m ()
repeatM_ :: forall (m :: * -> *) a. Monad m => m a -> m ()
repeatM_ = forall (m :: * -> *) a. Monad m => m a -> m ()
mvoid forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) t. Monad m => m t -> m [t]
repeatM

{- | Right to left compositon of 'Monad' functions.

> fmap (== 7) (composeM [return . (+ 1),return . (* 2)] 3)
> fmap (== 8) (composeM [return . (* 2),return . (+ 1)] 3)
-}
composeM :: Monad m => [a -> m a] -> a -> m a
composeM :: forall (m :: * -> *) a. Monad m => [a -> m a] -> a -> m a
composeM = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a -> m a
f a -> m a
g -> \a
x -> a -> m a
g a
x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> m a
f) forall (m :: * -> *) a. Monad m => a -> m a
return -- foldr (<=<) return except hugs doesn't know of <=<

{- | Feed forward composition of /n/ applications of /f/.

> fmap (== 3) (chainM 3 (return . (+ 1)) 0)
-}
chainM :: Monad m => Int -> (b -> m b) -> b -> m b
chainM :: forall (m :: * -> *) b. Monad m => Int -> (b -> m b) -> b -> m b
chainM Int
n b -> m b
f = forall (m :: * -> *) a. Monad m => [a -> m a] -> a -> m a
composeM (forall a. Int -> a -> [a]
replicate Int
n b -> m b
f)