-- |Misc combinators.
module Incipit.Misc where

import qualified Data.Foldable as Foldable

import Incipit.Base

-- |Convenience alias for @pure ()@.
unit ::
  Applicative f =>
  f ()
unit :: forall (f :: * -> *). Applicative f => f ()
unit =
  () -> f ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
{-# inline unit #-}

-- |Variant of 'when' that takes a monadic action for the condition.
whenM ::
  Monad m =>
  m Bool ->
  m () ->
  m ()
whenM :: forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
whenM m Bool
condM m ()
action =
  m Bool
condM m Bool -> (Bool -> m ()) -> m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ Bool
cond -> Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cond m ()
action
{-# inline whenM #-}

-- |Variant of 'unless' that takes a monadic action for the condition.
unlessM ::
  Monad m =>
  m Bool ->
  m () ->
  m ()
unlessM :: forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM m Bool
condM m ()
action =
  m Bool
condM m Bool -> (Bool -> m ()) -> m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ Bool
cond -> Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
cond m ()
action
{-# inline unlessM #-}

-- |Variant of @if@/@then@/@else@ that takes a monadic action for the condition and branches.
ifM ::
  Monad m =>
  m Bool ->
  m a ->
  m a ->
  m a
ifM :: forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifM m Bool
condM m a
onTrue m a
onFalse =
  m Bool
condM m Bool -> (Bool -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ Bool
cond -> if Bool
cond then m a
onTrue else m a
onFalse
{-# inline ifM #-}

-- |Default to using the strict version since the lazy one is so controversial.
foldl ::
   t b a .
  Foldable t =>
  (b -> a -> b) ->
  b ->
  t a ->
  b
foldl :: forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl =
  (b -> a -> b) -> b -> t a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
Foldable.foldl'
{-# inline foldl #-}