{-# OPTIONS_GHC -Wunused-imports #-}

-- | Missing utilities from "Control.Applicative".
module Mikan.Utils.Applicative
  ( (?*>)
  , (?$>)
  , foldA
  , foldMapA
  , liftA4
  )
  where

import Control.Applicative
import Data.Monoid ( Alt(..) )

{-# INLINABLE liftA4 #-}
-- | Lift quaternary functions to actions.
liftA4 :: Applicative f => (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e
liftA4 :: forall (f :: * -> *) a b c d e.
Applicative f =>
(a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e
liftA4 a -> b -> c -> d -> e
f f a
a f b
b f c
c f d
d = (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f (d -> e)
forall (f :: * -> *) a b c d.
Applicative f =>
(a -> b -> c -> d) -> f a -> f b -> f c -> f d
liftA3 a -> b -> c -> d -> e
f f a
a f b
b f c
c f (d -> e) -> f d -> f e
forall a b. f (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> f d
d

{-# INLINE (?*>) #-}
-- | Guard: return the action @f@ only if the boolean is @True@.
(?*>) :: Alternative f => Bool -> f a -> f a
Bool
b ?*> :: forall (f :: * -> *) a. Alternative f => Bool -> f a -> f a
?*> f a
f = if Bool
b then f a
f else f a
forall a. f a
forall (f :: * -> *) a. Alternative f => f a
empty

{-# INLINE (?$>) #-}
-- | Guard: return the value @a@ only if the boolean is @True@.
(?$>) :: Alternative f => Bool -> a -> f a
Bool
b ?$> :: forall (f :: * -> *) a. Alternative f => Bool -> a -> f a
?$> a
a = Bool
b Bool -> f a -> f a
forall (f :: * -> *) a. Alternative f => Bool -> f a -> f a
?*> a -> f a
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a

{-# INLINE foldA #-}
-- | Branch over a 'Foldable' collection of values.
foldA :: (Alternative f, Foldable t) => t a -> f a
foldA :: forall (f :: * -> *) (t :: * -> *) a.
(Alternative f, Foldable t) =>
t a -> f a
foldA = (a -> f a) -> t a -> f a
forall (f :: * -> *) (t :: * -> *) a b.
(Alternative f, Foldable t) =>
(a -> f b) -> t a -> f b
foldMapA a -> f a
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

{-# INLINE foldMapA #-}
-- | Branch over a 'Foldable' collection of values using the supplied
--   action.
foldMapA :: (Alternative f, Foldable t) => (a -> f b) -> t a -> f b
foldMapA :: forall (f :: * -> *) (t :: * -> *) a b.
(Alternative f, Foldable t) =>
(a -> f b) -> t a -> f b
foldMapA a -> f b
f = Alt f b -> f b
forall {k} (f :: k -> *) (a :: k). Alt f a -> f a
getAlt (Alt f b -> f b) -> (t a -> Alt f b) -> t a -> f b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Alt f b) -> t a -> Alt f b
forall m a. Monoid m => (a -> m) -> t a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (f b -> Alt f b
forall {k} (f :: k -> *) (a :: k). f a -> Alt f a
Alt (f b -> Alt f b) -> (a -> f b) -> a -> Alt f b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> f b
f)