{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Trustworthy #-}

-- |
-- Module      :   Grisette.Lib.Control.Traversable
-- Copyright   :   (c) Sirui Lu 2021-2023
-- License     :   BSD-3-Clause (see the LICENSE file)
--
-- Maintainer  :   siruilu@cs.washington.edu
-- Stability   :   Experimental
-- Portability :   GHC only
module Grisette.Lib.Data.Traversable
  ( -- * mrg* variants for operations in "Data.Traversable"
    mrgTraverse,
    mrgSequenceA,
    mrgFor,
    mrgMapM,
    mrgForM,
    mrgSequence,
  )
where

import Grisette.Core.Control.Monad.Union
import Grisette.Core.Data.Class.Mergeable
import Grisette.Core.Data.Class.SimpleMergeable

-- | 'Data.Traversable.traverse' with 'MergingStrategy' knowledge propagation.
mrgTraverse ::
  forall a b t f.
  ( Mergeable b,
    Mergeable1 t,
    MonadUnion f,
    Traversable t
  ) =>
  (a -> f b) ->
  t a ->
  f (t b)
mrgTraverse :: forall a b (t :: * -> *) (f :: * -> *).
(Mergeable b, Mergeable1 t, MonadUnion f, Traversable t) =>
(a -> f b) -> t a -> f (t b)
mrgTraverse a -> f b
f = MergingStrategy (t b) -> f (t b) -> f (t b)
forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy MergingStrategy (t b)
forall a (u :: * -> *).
(Mergeable a, Mergeable1 u) =>
MergingStrategy (u a)
rootStrategy1 (f (t b) -> f (t b)) -> (t a -> f (t b)) -> t a -> f (t b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> f b) -> t a -> f (t b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (f b -> f b
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => u a -> u a
merge (f b -> f b) -> (a -> f b) -> a -> f b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> f b
f)
{-# INLINE mrgTraverse #-}

-- | 'Data.Traversable.sequenceA' with 'MergingStrategy' knowledge propagation.
mrgSequenceA ::
  forall a t f.
  ( Mergeable a,
    Mergeable1 t,
    MonadUnion f,
    Traversable t
  ) =>
  t (f a) ->
  f (t a)
mrgSequenceA :: forall a (t :: * -> *) (f :: * -> *).
(Mergeable a, Mergeable1 t, MonadUnion f, Traversable t) =>
t (f a) -> f (t a)
mrgSequenceA = (f a -> f a) -> t (f a) -> f (t a)
forall a b (t :: * -> *) (f :: * -> *).
(Mergeable b, Mergeable1 t, MonadUnion f, Traversable t) =>
(a -> f b) -> t a -> f (t b)
mrgTraverse f a -> f a
forall a. a -> a
id
{-# INLINE mrgSequenceA #-}

-- | 'Data.Traversable.mapM' with 'MergingStrategy' knowledge propagation.
mrgMapM ::
  forall a b t f.
  ( Mergeable b,
    Mergeable1 t,
    MonadUnion f,
    Traversable t
  ) =>
  (a -> f b) ->
  t a ->
  f (t b)
mrgMapM :: forall a b (t :: * -> *) (f :: * -> *).
(Mergeable b, Mergeable1 t, MonadUnion f, Traversable t) =>
(a -> f b) -> t a -> f (t b)
mrgMapM = (a -> f b) -> t a -> f (t b)
forall a b (t :: * -> *) (f :: * -> *).
(Mergeable b, Mergeable1 t, MonadUnion f, Traversable t) =>
(a -> f b) -> t a -> f (t b)
mrgTraverse
{-# INLINE mrgMapM #-}

-- | 'Data.Traversable.sequence' with 'MergingStrategy' knowledge propagation.
mrgSequence ::
  forall a t f.
  ( Mergeable a,
    Mergeable1 t,
    MonadUnion f,
    Traversable t
  ) =>
  t (f a) ->
  f (t a)
mrgSequence :: forall a (t :: * -> *) (f :: * -> *).
(Mergeable a, Mergeable1 t, MonadUnion f, Traversable t) =>
t (f a) -> f (t a)
mrgSequence = t (f a) -> f (t a)
forall a (t :: * -> *) (f :: * -> *).
(Mergeable a, Mergeable1 t, MonadUnion f, Traversable t) =>
t (f a) -> f (t a)
mrgSequenceA
{-# INLINE mrgSequence #-}

-- | 'Data.Traversable.for' with 'MergingStrategy' knowledge propagation.
mrgFor ::
  ( Mergeable b,
    Mergeable1 t,
    Traversable t,
    MonadUnion m
  ) =>
  t a ->
  (a -> m b) ->
  m (t b)
mrgFor :: forall b (t :: * -> *) (m :: * -> *) a.
(Mergeable b, Mergeable1 t, Traversable t, MonadUnion m) =>
t a -> (a -> m b) -> m (t b)
mrgFor = ((a -> m b) -> t a -> m (t b)) -> t a -> (a -> m b) -> m (t b)
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> m b) -> t a -> m (t b)
forall a b (t :: * -> *) (f :: * -> *).
(Mergeable b, Mergeable1 t, MonadUnion f, Traversable t) =>
(a -> f b) -> t a -> f (t b)
mrgTraverse
{-# INLINE mrgFor #-}

-- | 'Data.Traversable.forM' with 'MergingStrategy' knowledge propagation.
mrgForM ::
  ( Mergeable b,
    Mergeable1 t,
    Traversable t,
    MonadUnion m
  ) =>
  t a ->
  (a -> m b) ->
  m (t b)
mrgForM :: forall b (t :: * -> *) (m :: * -> *) a.
(Mergeable b, Mergeable1 t, Traversable t, MonadUnion m) =>
t a -> (a -> m b) -> m (t b)
mrgForM = ((a -> m b) -> t a -> m (t b)) -> t a -> (a -> m b) -> m (t b)
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> m b) -> t a -> m (t b)
forall a b (t :: * -> *) (f :: * -> *).
(Mergeable b, Mergeable1 t, MonadUnion f, Traversable t) =>
(a -> f b) -> t a -> f (t b)
mrgMapM
{-# INLINE mrgForM #-}