packages feed

ten-0.1.0.0: src/Data/Ten/Foldable/WithIndex.hs

-- Copyright 2021 Google LLC
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.

-- | An extension of 'Foldable10' that provides access to some 'Index10'.

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}

module Data.Ten.Foldable.WithIndex
         ( Index10, Foldable10WithIndex(..)
         , ifoldl10, ifoldr10, itraverse10_
         , foldMap10C, foldr10C, foldl10C, traverse10C_
         ) where

import Data.Monoid (Dual(..), Endo(..))

import GHC.Generics ((:.:)(..))

import Data.Ten.Entails (Entails(..), byEntailment)
import Data.Ten.Foldable (Foldable10(..))
import Data.Ten.Functor.WithIndex (Index10)

-- | An extension of 'Foldable10' that provides access to some 'Index10'.
class Foldable10 f => Foldable10WithIndex f where
  ifoldMap10 :: Monoid w => (forall a. Index10 f a -> m a -> w) -> f m -> w

instance (Foldable g, Foldable10WithIndex f)
      => Foldable10WithIndex (g :.: f) where
  ifoldMap10 f (Comp1 gfm) = foldMap (ifoldMap10 f) gfm

-- | 'Data.Ten.Foldable.foldl10' with an index parameter.
ifoldl10
  :: Foldable10WithIndex f
  => (forall a. Index10 f a -> b -> m a -> b)
  -> b -> f m -> b
ifoldl10 f z fm = appEndo (ifoldMap10 (\i x -> Endo (\b -> f i b x)) fm) z

-- | 'Data.Ten.Foldable.foldr10' with an index parameter.
ifoldr10
  :: Foldable10WithIndex f
  => (forall a. Index10 f a -> m a -> b -> b) -> b -> f m -> b
ifoldr10 f z fm = flip appEndo z $ getDual $
  ifoldMap10 (\i x -> Dual $ Endo (f i x)) fm

-- | 'Data.Ten.Foldable.traverse10_' with an index parameter.
itraverse10_
  :: (Foldable10WithIndex f, Applicative g)
  => (forall a. Index10 f a -> m a -> g ())
  -> f m -> g ()
itraverse10_ f = ifoldl10 (\i a x -> a <* f i x) (pure ())

-- | 'Data.Ten.Foldable.foldMap10' with an instance for every element.
foldMap10C
  :: forall c f m w
   . (Entails (Index10 f) c, Foldable10WithIndex f, Monoid w)
  => (forall a. c a => m a -> w) -> f m -> w
foldMap10C f = ifoldMap10 (byEntailment @c f)

-- | 'Data.Ten.Foldable.foldr10' with an instance for every element.
foldr10C
  :: forall c f m b
   . (Entails (Index10 f) c, Foldable10WithIndex f)
  => (forall a. c a => m a -> b -> b) -> b -> f m -> b
foldr10C f = ifoldr10 (byEntailment @c f)

-- | 'Data.Ten.Foldable.foldl10' with an instance for every element.
foldl10C
  :: forall c f m b
   . (Entails (Index10 f) c, Foldable10WithIndex f)
  => (forall a. c a => b -> m a -> b) -> b -> f m -> b
foldl10C f = ifoldl10 (byEntailment @c f)

-- | 'Data.Ten.Foldable.traverse10_' with an instance for every element.
traverse10C_
  :: forall c f g m
   . (Entails (Index10 f) c, Applicative g, Foldable10WithIndex f)
  => (forall a. c a => m a -> g ()) -> f m -> g ()
traverse10C_ f = itraverse10_ (byEntailment @c f)