parameterized-utils-2.1.4.0: src/Data/Parameterized/TraversableFC/WithIndex.hs
------------------------------------------------------------------------
-- |
-- Module : Data.Parameterized.TraversableFC.WithIndex
-- Copyright : (c) Galois, Inc 2021
-- Maintainer : Langston Barrett
-- Description : 'TraversableFC' classes, but with indices.
--
-- As in the package indexed-traversable.
------------------------------------------------------------------------
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Data.Parameterized.TraversableFC.WithIndex
( FunctorFCWithIndex(..)
, FoldableFCWithIndex(..)
, ifoldlMFC
, ifoldrMFC
, iallFC
, ianyFC
, TraversableFCWithIndex(..)
, imapFCDefault
, ifoldMapFCDefault
) where
import Data.Functor.Const (Const(Const, getConst))
import Data.Functor.Identity (Identity(Identity, runIdentity))
import Data.Kind
import Data.Monoid (All(..), Any(..), Endo(Endo), appEndo, Dual(Dual, getDual))
import Data.Profunctor.Unsafe ((#.))
import GHC.Exts (build)
import Data.Parameterized.Classes
import Data.Parameterized.TraversableFC
class FunctorFC t => FunctorFCWithIndex (t :: (k -> Type) -> l -> Type) where
-- | Like 'fmapFC', but with an index.
--
-- @
-- 'fmapFC' f ≡ 'imapFC' ('const' f)
-- @
imapFC ::
forall f g z.
(forall x. IndexF (t f z) x -> f x -> g x)
-> t f z
-> t g z
------------------------------------------------------------------------
class (FoldableFC t, FunctorFCWithIndex t) => FoldableFCWithIndex (t :: (k -> Type) -> l -> Type) where
-- | Like 'foldMapFC', but with an index.
--
-- @
-- 'foldMapFC' f ≡ 'ifoldMapFC' ('const' f)
-- @
ifoldMapFC ::
forall f m z.
Monoid m =>
(forall x. IndexF (t f z) x -> f x -> m) ->
t f z ->
m
ifoldMapFC f = ifoldrFC (\i x -> mappend (f i x)) mempty
-- | Like 'foldrFC', but with an index.
ifoldrFC ::
forall z f b.
(forall x. IndexF (t f z) x -> f x -> b -> b) ->
b ->
t f z ->
b
ifoldrFC f z t = appEndo (ifoldMapFC (\i x -> Endo (f i x)) t) z
-- | Like 'foldlFC', but with an index.
ifoldlFC ::
forall f b z.
(forall x. IndexF (t f z) x -> b -> f x -> b) ->
b ->
t f z ->
b
ifoldlFC f z t =
appEndo (getDual (ifoldMapFC (\i e -> Dual (Endo (\r -> f i r e))) t)) z
-- | Like 'ifoldrFC', but with an index.
ifoldrFC' ::
forall f b z.
(forall x. IndexF (t f z) x -> f x -> b -> b) ->
b ->
t f z ->
b
ifoldrFC' f0 z0 xs = ifoldlFC (f' f0) id xs z0
where f' f i k x z = k $! f i x z
-- | Like 'ifoldlFC', but with an index.
ifoldlFC' :: forall f b. (forall x. b -> f x -> b) -> (forall x. b -> t f x -> b)
ifoldlFC' f0 z0 xs = foldrFC (f' f0) id xs z0
where f' f x k z = k $! f z x
-- | Convert structure to list.
itoListFC ::
forall f a z.
(forall x. IndexF (t f z) x -> f x -> a) ->
t f z ->
[a]
itoListFC f t = build (\c n -> ifoldrFC (\i e v -> c (f i e) v) n t)
-- | Like 'foldlMFC', but with an index.
ifoldlMFC ::
FoldableFCWithIndex t =>
Monad m =>
(forall x. IndexF (t f z) x -> b -> f x -> m b) ->
b ->
t f z ->
m b
ifoldlMFC f z0 xs = ifoldlFC (\i k x z -> f i z x >>= k) return xs z0
-- | Like 'foldrMFC', but with an index.
ifoldrMFC ::
FoldableFCWithIndex t =>
Monad m =>
(forall x. IndexF (t f z) x -> f x -> b -> m b) ->
b ->
t f z ->
m b
ifoldrMFC f z0 xs = ifoldlFC (\i k x z -> f i x z >>= k) return xs z0
-- | Like 'allFC', but with an index.
iallFC ::
FoldableFCWithIndex t =>
(forall x. IndexF (t f z) x -> f x -> Bool) ->
t f z ->
Bool
iallFC p = getAll #. ifoldMapFC (\i x -> All (p i x))
-- | Like 'anyFC', but with an index.
ianyFC ::
FoldableFCWithIndex t =>
(forall x. IndexF (t f z) x -> f x -> Bool) ->
t f z -> Bool
ianyFC p = getAny #. ifoldMapFC (\i x -> Any (p i x))
------------------------------------------------------------------------
class (TraversableFC t, FoldableFCWithIndex t) => TraversableFCWithIndex (t :: (k -> Type) -> l -> Type) where
-- | Like 'traverseFC', but with an index.
--
-- @
-- 'traverseFC' f ≡ 'itraverseFC' ('const' f)
-- @
itraverseFC ::
forall m z f g.
Applicative m =>
(forall x. IndexF (t f z) x -> f x -> m (g x)) ->
t f z ->
m (t g z)
imapFCDefault ::
forall t f g z.
TraversableFCWithIndex t =>
(forall x. IndexF (t f z) x -> f x -> g x)
-> t f z
-> t g z
imapFCDefault f = runIdentity #. itraverseFC (\i x -> Identity (f i x))
{-# INLINEABLE imapFCDefault #-}
ifoldMapFCDefault ::
forall t m z f.
TraversableFCWithIndex t =>
Monoid m =>
(forall x. IndexF (t f z) x -> f x -> m) ->
t f z ->
m
ifoldMapFCDefault f = getConst #. itraverseFC (\i x -> Const (f i x))
{-# INLINEABLE ifoldMapFCDefault #-}