module Unison.Util.Monoid
  ( foldMapM,
    ifoldMapM,
    Unison.Util.Monoid.fromMaybe,
    intercalateMap,
    intercalateMapM,
    isEmpty,
    nonEmpty,
    Unison.Util.Monoid.unlessM,
    whenM,
  )
where

import Control.Lens (TraversableWithIndex, ifor)
import Data.List (intersperse)
import Unison.Prelude hiding (whenM)

-- List.intercalate extended to any monoid
-- "The type that intercalate should have had to begin with."
intercalateMap :: (Foldable t, Monoid a) => a -> (b -> a) -> t b -> a
intercalateMap :: forall (t :: * -> *) a b.
(Foldable t, Monoid a) =>
a -> (b -> a) -> t b -> a
intercalateMap a
separator b -> a
renderer t b
elements =
  [a] -> a
forall a. Monoid a => [a] -> a
mconcat ([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ a -> [a] -> [a]
forall a. a -> [a] -> [a]
intersperse a
separator (b -> a
renderer (b -> a) -> [b] -> [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t b -> [b]
forall a. t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList t b
elements)

intercalateMapM :: (Traversable t, Monad m, Monoid a) => a -> (b -> m a) -> t b -> m a
intercalateMapM :: forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m, Monoid a) =>
a -> (b -> m a) -> t b -> m a
intercalateMapM a
separator b -> m a
renderer = (b -> m a) -> t b -> m (t a)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> t a -> f (t b)
traverse b -> m a
renderer (t b -> m (t a)) -> (t a -> m a) -> t b -> m a
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> m a) -> (t a -> a) -> t a -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> (a -> a) -> t a -> a
forall (t :: * -> *) a b.
(Foldable t, Monoid a) =>
a -> (b -> a) -> t b -> a
intercalateMap a
separator a -> a
forall a. a -> a
id

fromMaybe :: (Monoid a) => Maybe a -> a
fromMaybe :: forall a. Monoid a => Maybe a -> a
fromMaybe Maybe a
Nothing = a
forall a. Monoid a => a
mempty
fromMaybe (Just a
a) = a
a

whenM, unlessM :: (Monoid a) => Bool -> a -> a
whenM :: forall a. Monoid a => Bool -> a -> a
whenM Bool
True a
a = a
a
whenM Bool
False a
_ = a
forall a. Monoid a => a
mempty
unlessM :: forall a. Monoid a => Bool -> a -> a
unlessM = Bool -> a -> a
forall a. Monoid a => Bool -> a -> a
whenM (Bool -> a -> a) -> (Bool -> Bool) -> Bool -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not

isEmpty, nonEmpty :: (Eq a, Monoid a) => a -> Bool
isEmpty :: forall a. (Eq a, Monoid a) => a -> Bool
isEmpty a
a = a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Monoid a => a
mempty
nonEmpty :: forall a. (Eq a, Monoid a) => a -> Bool
nonEmpty = Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
forall a. (Eq a, Monoid a) => a -> Bool
isEmpty

foldMapM :: (Monad m, Foldable f, Monoid b) => (a -> m b) -> f a -> m b
foldMapM :: forall (m :: * -> *) (f :: * -> *) b a.
(Monad m, Foldable f, Monoid b) =>
(a -> m b) -> f a -> m b
foldMapM a -> m b
f f a
as = (b -> a -> m b) -> b -> f a -> m b
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (\b
b a
a -> (b -> b) -> m b -> m b
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (b
b b -> b -> b
forall a. Semigroup a => a -> a -> a
<>) (a -> m b
f a
a)) b
forall a. Monoid a => a
mempty f a
as

ifoldMapM :: (Monoid r, Applicative f, Foldable t, TraversableWithIndex i t) => (i -> a -> f r) -> t a -> f r
ifoldMapM :: forall r (f :: * -> *) (t :: * -> *) i a.
(Monoid r, Applicative f, Foldable t, TraversableWithIndex i t) =>
(i -> a -> f r) -> t a -> f r
ifoldMapM i -> a -> f r
f t a
xs = t r -> r
forall m. Monoid m => t m -> m
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold (t r -> r) -> f (t r) -> f r
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t a -> (i -> a -> f r) -> f (t r)
forall i (t :: * -> *) (f :: * -> *) a b.
(TraversableWithIndex i t, Applicative f) =>
t a -> (i -> a -> f b) -> f (t b)
ifor t a
xs i -> a -> f r
f