-----------------------------------------------------------------------------
-- |
-- Module:  Data.Functor.Barbie
--
-- Functors from indexed-types to types.
----------------------------------------------------------------------------
module Data.Functor.Barbie
  ( -- * Functor
    Func.FunctorB(bmap)

    -- * Traversable
  , Trav.TraversableB(btraverse)
    -- ** Utility functions
  , Trav.btraverse_
  , Trav.bfoldMap
  , Trav.bsequence
  , Trav.bsequence'

    -- * Applicative
  , Appl.ApplicativeB(bpure, bprod)
    -- ** Utility functions
  , Appl.bzip
  , Appl.bunzip
  , Appl.bzipWith
  , Appl.bzipWith3
  , Appl.bzipWith4

    -- * Constraints and instance dictionaries
    -- | Consider the following function:
    --
    -- @
    -- showIt :: 'Show' a => 'Maybe' a -> 'Data.Functor.Const' 'String' a
    -- showIt = 'Data.Functor.Const' . 'show'
    -- @
    --
    -- We would then like to be able to do:
    --
    -- @
    -- 'Data.Functor.Barbie.bmap' @showIt@ :: 'Data.Functor.Barbie.FunctorB' b => b 'Maybe' -> b ('Data.Functor.Const' 'String')
    -- @
    --
    -- This however doesn't work because of the @('Show' a)@ constraint in the
    -- the type of @showIt@.
    --
    -- The 'Cons.ConstraintsB' class let us overcome this problem.

  , Cons.ConstraintsB(..)
  , Cons.AllBF

    -- ** Utility functions
  , Cons.bdicts
  , Cons.bmapC
  , Cons.bfoldMapC
  , Cons.btraverseC
  , Cons.bpureC
  , Cons.bzipWithC
  , Cons.bzipWith3C
  , Cons.bzipWith4C
  , Cons.bmempty

    -- * Support for generic derivations
  , GenericN.Rec(..)
  )

where

import qualified Barbies.Internal.ApplicativeB as Appl
import qualified Barbies.Internal.ConstraintsB as Cons
import qualified Barbies.Internal.FunctorB as Func
import qualified Barbies.Internal.TraversableB as Trav

import qualified Data.Generics.GenericN as GenericN