    {-# LANGUAGE BangPatterns           #-}
    {-# LANGUAGE CPP                    #-}
    {-# LANGUAGE FlexibleInstances      #-}
    {-# LANGUAGE FunctionalDependencies #-}
    {-# LANGUAGE PolyKinds              #-}
    {-# LANGUAGE Trustworthy            #-}
    {-# LANGUAGE UndecidableInstances   #-}
    {-# OPTIONS_GHC -fno-warn-orphans #-}
    -- | Extra instances for 'FunctorWithIndex', 'FoldableWithIndex',
    -- and 'TraversableWithIndex' type classes.
    module Data.Functor.WithIndex.Instances () where

    import Prelude (Int, flip, (.))

    import Control.Applicative ((<$>))
    import Data.HashMap.Lazy   (HashMap)
    import Data.Tagged         (Tagged (..))
    import Data.Vector         (Vector)

    #if MIN_VERSION_OneTuple(0,4,0)
    import Data.Tuple.Solo     (Solo (MkSolo))
    #else
    import Data.Tuple.Solo     (Solo (Solo))
    #define MkSolo Solo
    #endif

    import qualified Data.HashMap.Lazy as HM
    import qualified Data.Vector       as V

    import Data.Foldable.WithIndex
    import Data.Functor.WithIndex
    import Data.Traversable.WithIndex

    -------------------------------------------------------------------------------
    -- tagged
    -------------------------------------------------------------------------------

    instance FunctorWithIndex () (Tagged a) where
      imap :: forall a b. (() -> a -> b) -> Tagged a a -> Tagged a b
    imap () -> a -> b
    f (Tagged a
    a) = b -> Tagged a b
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged (() -> a -> b
    f () a
    a)
      {-# INLINE imap #-}

    instance FoldableWithIndex () (Tagged a) where
      ifoldMap :: forall m a. Monoid m => (() -> a -> m) -> Tagged a a -> m
    ifoldMap () -> a -> m
    f (Tagged a
    a) = () -> a -> m
    f () a
    a
      {-# INLINE ifoldMap #-}

    instance TraversableWithIndex () (Tagged a) where
      itraverse :: forall (f :: * -> *) a b.
    Applicative f =>
    (() -> a -> f b) -> Tagged a a -> f (Tagged a b)
    itraverse () -> a -> f b
    f (Tagged a
    a) = b -> Tagged a b
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged (b -> Tagged a b) -> f b -> f (Tagged a b)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> () -> a -> f b
    f () a
    a
      {-# INLINE itraverse #-}

    -------------------------------------------------------------------------------
    -- vector
    -------------------------------------------------------------------------------

    instance FunctorWithIndex Int Vector where
      imap :: forall a b. (Int -> a -> b) -> Vector a -> Vector b
    imap = (Int -> a -> b) -> Vector a -> Vector b
    forall a b. (Int -> a -> b) -> Vector a -> Vector b
    V.imap
      {-# INLINE imap #-}
    instance FoldableWithIndex Int Vector where
      ifoldr :: forall a b. (Int -> a -> b -> b) -> b -> Vector a -> b
    ifoldr = (Int -> a -> b -> b) -> b -> Vector a -> b
    forall a b. (Int -> a -> b -> b) -> b -> Vector a -> b
    V.ifoldr
      {-# INLINE ifoldr #-}
      ifoldl :: forall b a. (Int -> b -> a -> b) -> b -> Vector a -> b
    ifoldl = (b -> Int -> a -> b) -> b -> Vector a -> b
    forall a b. (a -> Int -> b -> a) -> a -> Vector b -> a
    V.ifoldl ((b -> Int -> a -> b) -> b -> Vector a -> b)
    -> ((Int -> b -> a -> b) -> b -> Int -> a -> b)
    -> (Int -> b -> a -> b)
    -> b
    -> Vector a
    -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Int -> b -> a -> b) -> b -> Int -> a -> b
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip
      {-# INLINE ifoldl #-}
      ifoldr' :: forall a b. (Int -> a -> b -> b) -> b -> Vector a -> b
    ifoldr' = (Int -> a -> b -> b) -> b -> Vector a -> b
    forall a b. (Int -> a -> b -> b) -> b -> Vector a -> b
    V.ifoldr'
      {-# INLINE ifoldr' #-}
      ifoldl' :: forall b a. (Int -> b -> a -> b) -> b -> Vector a -> b
    ifoldl' = (b -> Int -> a -> b) -> b -> Vector a -> b
    forall a b. (a -> Int -> b -> a) -> a -> Vector b -> a
    V.ifoldl' ((b -> Int -> a -> b) -> b -> Vector a -> b)
    -> ((Int -> b -> a -> b) -> b -> Int -> a -> b)
    -> (Int -> b -> a -> b)
    -> b
    -> Vector a
    -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Int -> b -> a -> b) -> b -> Int -> a -> b
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip
      {-# INLINE ifoldl' #-}
    instance TraversableWithIndex Int Vector where
      itraverse :: forall (f :: * -> *) a b.
    Applicative f =>
    (Int -> a -> f b) -> Vector a -> f (Vector b)
    itraverse Int -> a -> f b
    f Vector a
    v =
        let !n :: Int
    n = Vector a -> Int
    forall a. Vector a -> Int
    V.length Vector a
    v in Int -> [b] -> Vector b
    forall a. Int -> [a] -> Vector a
    V.fromListN Int
    n ([b] -> Vector b) -> f [b] -> f (Vector b)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Int -> a -> f b) -> [a] -> f [b]
    forall i (t :: * -> *) (f :: * -> *) a b.
    (TraversableWithIndex i t, Applicative f) =>
    (i -> a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (Int -> a -> f b) -> [a] -> f [b]
    itraverse Int -> a -> f b
    f (Vector a -> [a]
    forall a. Vector a -> [a]
    V.toList Vector a
    v)
      {-# INLINE itraverse #-}

    -------------------------------------------------------------------------------
    -- unordered-containers
    -------------------------------------------------------------------------------

    instance FunctorWithIndex k (HashMap k) where
      imap :: forall a b. (k -> a -> b) -> HashMap k a -> HashMap k b
    imap = (k -> a -> b) -> HashMap k a -> HashMap k b
    forall k a b. (k -> a -> b) -> HashMap k a -> HashMap k b
    HM.mapWithKey
      {-# INLINE imap #-}
    instance FoldableWithIndex k (HashMap k) where
      ifoldr :: forall a b. (k -> a -> b -> b) -> b -> HashMap k a -> b
    ifoldr  = (k -> a -> b -> b) -> b -> HashMap k a -> b
    forall k a b. (k -> a -> b -> b) -> b -> HashMap k a -> b
    HM.foldrWithKey
      ifoldl' :: forall b a. (k -> b -> a -> b) -> b -> HashMap k a -> b
    ifoldl' = (b -> k -> a -> b) -> b -> HashMap k a -> b
    forall a k v. (a -> k -> v -> a) -> a -> HashMap k v -> a
    HM.foldlWithKey' ((b -> k -> a -> b) -> b -> HashMap k a -> b)
    -> ((k -> b -> a -> b) -> b -> k -> a -> b)
    -> (k -> b -> a -> b)
    -> b
    -> HashMap k a
    -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (k -> b -> a -> b) -> b -> k -> a -> b
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip
      {-# INLINE ifoldr #-}
      {-# INLINE ifoldl' #-}
    instance TraversableWithIndex k (HashMap k) where
      itraverse :: forall (f :: * -> *) a b.
    Applicative f =>
    (k -> a -> f b) -> HashMap k a -> f (HashMap k b)
    itraverse = (k -> a -> f b) -> HashMap k a -> f (HashMap k b)
    forall (f :: * -> *) k v1 v2.
    Applicative f =>
    (k -> v1 -> f v2) -> HashMap k v1 -> f (HashMap k v2)
    HM.traverseWithKey
      {-# INLINE itraverse #-}

    -------------------------------------------------------------------------------
    -- OneTuple
    -------------------------------------------------------------------------------

    instance FunctorWithIndex () Solo where
      imap :: forall a b. (() -> a -> b) -> Solo a -> Solo b
    imap () -> a -> b
    f (MkSolo a
    a) = b -> Solo b
    forall a. a -> Solo a
    MkSolo (() -> a -> b
    f () a
    a)
      {-# INLINE imap #-}

    instance FoldableWithIndex () Solo where
      ifoldMap :: forall m a. Monoid m => (() -> a -> m) -> Solo a -> m
    ifoldMap () -> a -> m
    f (MkSolo a
    a) = () -> a -> m
    f () a
    a
      {-# INLINE ifoldMap #-}

    instance TraversableWithIndex () Solo where
      itraverse :: forall (f :: * -> *) a b.
    Applicative f =>
    (() -> a -> f b) -> Solo a -> f (Solo b)
    itraverse () -> a -> f b
    f (MkSolo a
    a) = b -> Solo b
    forall a. a -> Solo a
    MkSolo (b -> Solo b) -> f b -> f (Solo b)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> () -> a -> f b
    f () a
    a
      {-# INLINE itraverse #-}