{-# LANGUAGE Safe #-}

-- |
-- Module      :  Data.Traversable
-- Copyright   :  Conor McBride and Ross Paterson 2005
-- License     :  BSD-style (see the LICENSE file in the distribution)
--
-- Maintainer  :  libraries@haskell.org
-- Stability   :  stable
-- Portability :  portable
--
-- Class of data structures that can be traversed from left to right,
-- performing an action on each element.  Instances are expected to satisfy
-- the listed [laws](#laws).

module Data.Traversable (
    -- * The 'Traversable' class
    Traversable(..),
    -- * Utility functions
    for,
    forM,
    forAccumM,
    mapAccumL,
    mapAccumR,
    mapAccumM,
    -- * General definitions for superclass methods
    fmapDefault,
    foldMapDefault,

    -- * Overview
    -- $overview

    -- ** The 'traverse' and 'mapM' methods
    -- $traverse

    -- *** Their 'Foldable', just the effects, analogues.
    -- $effectful

    -- *** Result multiplicity
    -- $multiplicity

    -- ** The 'sequenceA' and 'sequence' methods
    -- $sequence

    -- *** Care with default method implementations
    -- $seqdefault

    -- *** Monadic short circuits
    -- $seqshort

    -- ** Example binary tree instance
    -- $tree_instance

    -- *** Pre-order and post-order tree traversal
    -- $tree_order

    -- ** Making construction intuitive
    --
    -- $construction

    -- * Advanced traversals
    -- $advanced

    -- *** Coercion
    -- $coercion

    -- ** Identity: the 'fmapDefault' function
    -- $identity

    -- ** State: the 'mapAccumL', 'mapAccumR' functions
    -- $stateful

    -- ** Const: the 'foldMapDefault' function
    -- $phantom

    -- ** ZipList: transposing lists of lists
    -- $ziplist

    -- * Laws
    --
    -- $laws

    -- * See also
    -- $also
    ) where

import GHC.Internal.Data.Traversable

-- $setup
-- >>> import Prelude
-- >>> import Data.Maybe
-- >>> import Data.Either
-- >>> import qualified Data.List as List
-- >>> :set -XExplicitForAll

-- $overview
--
-- #overview#
-- Traversable structures support element-wise sequencing of 'Applicative'
-- effects (thus also 'Monad' effects) to construct new structures of
-- __the same shape__ as the input.
--
-- To illustrate what is meant by /same shape/, if the input structure is
-- __@[a]@__, each output structure is a list __@[b]@__ of the same length as
-- the input.  If the input is a __@Tree a@__, each output __@Tree b@__ has the
-- same graph of intermediate nodes and leaves.  Similarly, if the input is a
-- 2-tuple __@(x, a)@__, each output is a 2-tuple __@(x, b)@__, and so forth.
--
-- It is in fact possible to decompose a traversable structure __@t a@__ into
-- its shape (a.k.a. /spine/) of type __@t ()@__ and its element list
-- __@[a]@__.  The original structure can be faithfully reconstructed from its
-- spine and element list.
--
-- The implementation of a @Traversable@ instance for a given structure follows
-- naturally from its type; see the [Construction](#construction) section for
-- details.
-- Instances must satisfy the laws listed in the [Laws section](#laws).
-- The diverse uses of @Traversable@ structures result from the many possible
-- choices of Applicative effects.
-- See the [Advanced Traversals](#advanced) section for some examples.
--
-- Every @Traversable@ structure is both a 'Functor' and 'Foldable' because it
-- is possible to implement the requisite instances in terms of 'traverse' by
-- using 'fmapDefault' for 'fmap' and 'foldMapDefault' for 'foldMap'.  Direct
-- fine-tuned implementations of these superclass methods can in some cases be
-- more efficient.

------------------

-- $traverse
-- For an 'Applicative' functor __@f@__ and a @Traversable@ functor __@t@__,
-- the type signatures of 'traverse' and 'fmap' are rather similar:
--
-- > fmap     :: (a -> f b) -> t a -> t (f b)
-- > traverse :: (a -> f b) -> t a -> f (t b)
--
-- The key difference is that 'fmap' produces a structure whose elements (of
-- type __@f b@__) are individual effects, while 'traverse' produces an
-- aggregate effect yielding structures of type __@t b@__.
--
-- For example, when __@f@__ is the __@IO@__ monad, and __@t@__ is __@List@__,
-- 'fmap' yields a list of IO actions, whereas 'traverse' constructs an IO
-- action that evaluates to a list of the return values of the individual
-- actions performed left-to-right.
--
-- > traverse :: (a -> IO b) -> [a] -> IO [b]
--
-- The 'mapM' function is a specialisation of 'traverse' to the case when
-- __@f@__ is a 'Monad'.  For monads, 'mapM' is more idiomatic than 'traverse'.
-- The two are otherwise generally identical (though 'mapM' may be specifically
-- optimised for monads, and could be more efficient than using the more
-- general 'traverse').
--
-- > traverse :: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)
-- > mapM     :: (Monad       m, Traversable t) => (a -> m b) -> t a -> m (t b)
--
-- When the traversable term is a simple variable or expression, and the
-- monadic action to run is a non-trivial do block, it can be more natural to
-- write the action last.  This idiom is supported by 'for', 'forM', and
-- 'forAccumM' which are the flipped versions of 'traverse', 'mapM', and
-- 'mapAccumM' respectively.

------------------

-- $multiplicity
--
-- #multiplicity#
-- When 'traverse' or 'mapM' is applied to an empty structure __@ts@__ (one for
-- which __@'null' ts@__ is 'True') the return value is __@pure ts@__
-- regardless of the provided function __@g :: a -> f b@__.  It is not possible
-- to apply the function when no values of type __@a@__ are available, but its
-- type determines the relevant instance of 'pure'.
--
-- prop> null ts ==> traverse g ts == pure ts
--
-- Otherwise, when __@ts@__ is non-empty and at least one value of type __@b@__
-- results from each __@f a@__, the structures __@t b@__ have /the same shape/
-- (list length, graph of tree nodes, ...) as the input structure __@t a@__,
-- but the slots previously occupied by elements of type __@a@__ now hold
-- elements of type __@b@__.
--
-- A single traversal may produce one, zero or many such structures.  The zero
-- case happens when one of the effects __@f a@__ sequenced as part of the
-- traversal yields no replacement values.  Otherwise, the many case happens
-- when one of sequenced effects yields multiple values.
--
-- The 'traverse' function does not perform selective filtering of slots in the
-- output structure as with e.g. 'Data.Maybe.mapMaybe'.
--
-- >>> let incOdd n = if odd n then Just $ n + 1 else Nothing
-- >>> mapMaybe incOdd [1, 2, 3]
-- [2,4]
-- >>> traverse incOdd [1, 3, 5]
-- Just [2,4,6]
-- >>> traverse incOdd [1, 2, 3]
-- Nothing
--
-- In the above examples, with 'Maybe' as the 'Applicative' __@f@__, we see
-- that the number of __@t b@__ structures produced by 'traverse' may differ
-- from one: it is zero when the result short-circuits to __@Nothing@__.  The
-- same can happen when __@f@__ is __@List@__ and the result is __@[]@__, or
-- __@f@__ is __@Either e@__ and the result is __@Left (x :: e)@__, or perhaps
-- the 'Control.Applicative.empty' value of some
-- 'Control.Applicative.Alternative' functor.
--
-- When __@f@__ is e.g. __@List@__, and the map __@g :: a -> [b]@__ returns
-- more than one value for some inputs __@a@__ (and at least one for all
-- __@a@__), the result of __@mapM g ts@__ will contain multiple structures of
-- the same shape as __@ts@__:
--
-- prop> List.length (mapM g ts) == List.product (fmap (List.length . g) ts)
--
-- For example:
--
-- >>> List.length $ mapM (\n -> [1..n]) [1..6]
-- 720
-- >>> List.product $ List.length . (\n -> [1..n]) <$> [1..6]
-- 720
--
-- In other words, a traversal with a function __@g :: a -> [b]@__, over an
-- input structure __@t a@__, yields a list __@[t b]@__, whose length is the
-- product of the lengths of the lists that @g@ returns for each element of the
-- input structure!  The individual elements __@a@__ of the structure are
-- replaced by each element of __@g a@__ in turn:
--
-- >>> mapM (\n -> [1..n]) $ Just 3
-- [Just 1,Just 2,Just 3]
-- >>> mapM (\n -> [1..n]) [1..3]
-- [[1,1,1],[1,1,2],[1,1,3],[1,2,1],[1,2,2],[1,2,3]]
--
-- If any element of the structure __@t a@__ is mapped by @g@ to an empty list,
-- then the entire aggregate result is empty, because no value is available to
-- fill one of the slots of the output structure:
--
-- >>> mapM (\n -> [1..n]) $ [0..6] -- [1..0] is empty
-- []

------------------

-- $effectful
-- #effectful#
--
-- The 'traverse' and 'mapM' methods have analogues in the "Data.Foldable"
-- module.  These are 'traverse_' and 'mapM_', and their flipped variants
-- 'for_' and 'forM_', respectively.  The result type is __@f ()@__, they don't
-- return an updated structure, and can be used to sequence effects over all
-- the elements of a @Traversable@ (any 'Foldable') structure just for their
-- side-effects.
--
-- If the @Traversable@ structure is empty, the result is __@pure ()@__.  When
-- effects short-circuit, the __@f ()@__ result may, for example, be 'Nothing'
-- if __@f@__ is 'Maybe', or __@'Left' e@__ when it is __@'Either' e@__.
--
-- It is perhaps worth noting that 'Maybe' is not only a potential
-- 'Applicative' functor for the return value of the first argument of
-- 'traverse', but is also itself a 'Traversable' structure with either zero or
-- one element.  A convenient idiom for conditionally executing an action just
-- for its effects on a 'Just' value, and doing nothing otherwise is:
--
-- > -- action :: Monad m => a -> m ()
-- > -- mvalue :: Maybe a
-- > mapM_ action mvalue -- :: m ()
--
-- which is more concise than:
--
-- > maybe (return ()) action mvalue
--
-- The 'mapM_' idiom works verbatim if the type of __@mvalue@__ is later
-- refactored from __@Maybe a@__ to __@Either e a@__ (assuming it remains OK to
-- silently do nothing in the 'Left' case).

------------------

-- $sequence
--
-- #sequence#
-- The 'sequenceA' and 'sequence' methods are useful when what you have is a
-- container of pending applicative or monadic effects, and you want to combine
-- them into a single effect that produces zero or more containers with the
-- computed values.
--
-- > sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)
-- > sequence  :: (Monad       m, Traversable t) => t (m a) -> m (t a)
-- > sequenceA = traverse id -- default definition
-- > sequence  = sequenceA   -- default definition
--
-- When the monad __@m@__ is 'System.IO.IO', applying 'sequence' to a list of
-- IO actions, performs each in turn, returning a list of the results:
--
-- > sequence [putStr "Hello ", putStrLn "World!"]
-- >     = (\a b -> [a,b]) <$> putStr "Hello " <*> putStrLn "World!"
-- >     = do u1 <- putStr "Hello "
-- >          u2 <- putStrLn "World!"
-- >          return [u1, u2]         -- In this case  [(), ()]
--
-- For 'sequenceA', the /non-deterministic/ behaviour of @List@ is most easily
-- seen in the case of a list of lists (of elements of some common fixed type).
-- The result is a cross-product of all the sublists:
--
-- >>> sequenceA [[0, 1, 2], [30, 40], [500]]
-- [[0,30,500],[0,40,500],[1,30,500],[1,40,500],[2,30,500],[2,40,500]]
--
-- Because the input list has three (sublist) elements, the result is a list of
-- triples (/same shape/).

------------------

-- $seqshort
--
-- #seqshort#
-- When the monad __@m@__ is 'Either' or 'Maybe' (more generally any
-- 'Control.Monad.MonadPlus'), the effect in question is to short-circuit the
-- result on encountering 'Left' or 'Nothing' (more generally
-- 'Control.Monad.mzero').
--
-- >>> sequence [Just 1,Just 2,Just 3]
-- Just [1,2,3]
-- >>> sequence [Just 1,Nothing,Just 3]
-- Nothing
-- >>> sequence [Right 1,Right 2,Right 3]
-- Right [1,2,3]
-- >>> sequence [Right 1,Left "sorry",Right 3]
-- Left "sorry"
--
-- The result of 'sequence' is all-or-nothing, either structures of exactly the
-- same shape as the input or none at all.  The 'sequence' function does not
-- perform selective filtering as with e.g. 'Data.Maybe.catMaybes' or
-- 'Data.Either.rights':
--
-- >>> catMaybes [Just 1,Nothing,Just 3]
-- [1,3]
-- >>> rights [Right 1,Left "sorry",Right 3]
-- [1,3]

------------------

-- $seqdefault
--
-- #seqdefault#
-- The 'traverse' method has a default implementation in terms of 'sequenceA':
--
-- > traverse g = sequenceA . fmap g
--
-- but relying on this default implementation is not recommended, it requires
-- that the structure is already independently a 'Functor'.  The definition of
-- 'sequenceA' in terms of __@traverse id@__ is much simpler than 'traverse'
-- expressed via a composition of 'sequenceA' and 'fmap'.  Instances should
-- generally implement 'traverse' explicitly.  It may in some cases also make
-- sense to implement a specialised 'mapM'.
--
-- Because 'fmapDefault' is defined in terms of 'traverse' (whose default
-- definition in terms of 'sequenceA' uses 'fmap'), you must not use
-- 'fmapDefault' to define the @Functor@ instance if the @Traversable@ instance
-- directly defines only 'sequenceA'.

------------------

-- $tree_instance
--
-- #tree#
-- The definition of a 'Traversable' instance for a binary tree is rather
-- similar to the corresponding instance of 'Functor', given the data type:
--
-- > data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)
--
-- a canonical @Functor@ instance would be
--
-- > instance Functor Tree where
-- >    fmap g Empty        = Empty
-- >    fmap g (Leaf x)     = Leaf (g x)
-- >    fmap g (Node l k r) = Node (fmap g l) (g k) (fmap g r)
--
-- a canonical @Traversable@ instance would be
--
-- > instance Traversable Tree where
-- >    traverse g Empty        = pure Empty
-- >    traverse g (Leaf x)     = Leaf <$> g x
-- >    traverse g (Node l k r) = Node <$> traverse g l <*> g k <*> traverse g r
--
-- This definition works for any __@g :: a -> f b@__, with __@f@__ an
-- Applicative functor, as the laws for @('<*>')@ imply the requisite
-- associativity.
--
-- We can add an explicit non-default 'mapM' if desired:
--
-- >    mapM g Empty        = return Empty
-- >    mapM g (Leaf x)     = Leaf <$> g x
-- >    mapM g (Node l k r) = do
-- >        ml <- mapM g l
-- >        mk <- g k
-- >        mr <- mapM g r
-- >        return $ Node ml mk mr
--
-- See [Construction](#construction) below for a more detailed exploration of
-- the general case, but as mentioned in [Overview](#overview) above, instance
-- definitions are typically rather simple, all the interesting behaviour is a
-- result of an interesting choice of 'Applicative' functor for a traversal.

-- $tree_order
--
-- It is perhaps worth noting that the traversal defined above gives an
-- /in-order/ sequencing of the elements.  If instead you want either
-- /pre-order/ (parent first, then child nodes) or post-order (child nodes
-- first, then parent) sequencing, you can define the instance accordingly:
--
-- > inOrderNode :: Tree a -> a -> Tree a -> Tree a
-- > inOrderNode l x r = Node l x r
-- >
-- > preOrderNode :: a -> Tree a -> Tree a -> Tree a
-- > preOrderNode x l r = Node l x r
-- >
-- > postOrderNode :: Tree a -> Tree a -> a -> Tree a
-- > postOrderNode l r x = Node l x r
-- >
-- > -- Traversable instance with in-order traversal
-- > instance Traversable Tree where
-- >     traverse g t = case t of
-- >         Empty      -> pure Empty
-- >         Leaf x     -> Leaf <$> g x
-- >         Node l x r -> inOrderNode <$> traverse g l <*> g x <*> traverse g r
-- >
-- > -- Traversable instance with pre-order traversal
-- > instance Traversable Tree where
-- >     traverse g t = case t of
-- >         Empty      -> pure Empty
-- >         Leaf x     -> Leaf <$> g x
-- >         Node l x r -> preOrderNode <$> g x <*> traverse g l <*> traverse g r
-- >
-- > -- Traversable instance with post-order traversal
-- > instance Traversable Tree where
-- >     traverse g t = case t of
-- >         Empty      -> pure Empty
-- >         Leaf x     -> Leaf <$> g x
-- >         Node l x r -> postOrderNode <$> traverse g l <*> traverse g r <*> g x
--
-- Since the same underlying Tree structure is used in all three cases, it is
-- possible to use @newtype@ wrappers to make all three available at the same
-- time!  The user need only wrap the root of the tree in the appropriate
-- @newtype@ for the desired traversal order.  Tne associated instance
-- definitions are shown below (see [coercion](#coercion) if unfamiliar with
-- the use of 'coerce' in the sample code):
--
-- > {-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
-- >
-- > -- Default in-order traversal
-- >
-- > import Data.Coerce (coerce)
-- > import Data.Traversable
-- >
-- > data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)
-- > instance Functor  Tree where fmap    = fmapDefault
-- > instance Foldable Tree where foldMap = foldMapDefault
-- >
-- > instance Traversable Tree where
-- >     traverse _ Empty = pure Empty
-- >     traverse g (Leaf a) = Leaf <$> g a
-- >     traverse g (Node l a r) = Node <$> traverse g l <*> g a <*> traverse g r
-- >
-- > -- Optional pre-order traversal
-- >
-- > newtype PreOrderTree a = PreOrderTree (Tree a)
-- > instance Functor  PreOrderTree where fmap    = fmapDefault
-- > instance Foldable PreOrderTree where foldMap = foldMapDefault
-- >
-- > instance Traversable PreOrderTree where
-- >     traverse _ (PreOrderTree Empty)        = pure $ preOrderEmpty
-- >     traverse g (PreOrderTree (Leaf x))     = preOrderLeaf <$> g x
-- >     traverse g (PreOrderTree (Node l x r)) = preOrderNode
-- >         <$> g x
-- >         <*> traverse g (coerce l)
-- >         <*> traverse g (coerce r)
-- >
-- > preOrderEmpty :: forall a. PreOrderTree a
-- > preOrderEmpty = coerce (Empty @a)
-- > preOrderLeaf :: forall a. a -> PreOrderTree a
-- > preOrderLeaf = coerce (Leaf @a)
-- > preOrderNode :: a -> PreOrderTree a -> PreOrderTree a -> PreOrderTree a
-- > preOrderNode x l r = coerce (Node (coerce l) x (coerce r))
-- >
-- > -- Optional post-order traversal
-- >
-- > newtype PostOrderTree a = PostOrderTree (Tree a)
-- > instance Functor  PostOrderTree where fmap    = fmapDefault
-- > instance Foldable PostOrderTree where foldMap = foldMapDefault
-- >
-- > instance Traversable PostOrderTree where
-- >     traverse _ (PostOrderTree Empty)        = pure postOrderEmpty
-- >     traverse g (PostOrderTree (Leaf x))     = postOrderLeaf <$> g x
-- >     traverse g (PostOrderTree (Node l x r)) = postOrderNode
-- >         <$> traverse g (coerce l)
-- >         <*> traverse g (coerce r)
-- >         <*> g x
-- >
-- > postOrderEmpty :: forall a. PostOrderTree a
-- > postOrderEmpty = coerce (Empty @a)
-- > postOrderLeaf :: forall a. a -> PostOrderTree a
-- > postOrderLeaf = coerce (Leaf @a)
-- > postOrderNode :: PostOrderTree a -> PostOrderTree a -> a -> PostOrderTree a
-- > postOrderNode l r x = coerce (Node (coerce l) x (coerce r))
--
-- With the above, given a sample tree:
--
-- > inOrder :: Tree Int
-- > inOrder = Node (Node (Leaf 10) 3 (Leaf 20)) 5 (Leaf 42)
--
-- we have:
--
-- > import Data.Foldable (toList)
-- > print $ toList inOrder
-- > [10,3,20,5,42]
-- >
-- > print $ toList (coerce inOrder :: PreOrderTree Int)
-- > [5,3,10,20,42]
-- >
-- > print $ toList (coerce inOrder :: PostOrderTree Int)
-- > [10,20,3,42,5]
--
-- You would typically define instances for additional common type classes,
-- such as 'Eq', 'Ord', 'Show', etc.

------------------

-- $construction
--
-- #construction#
-- In order to be able to reason about how a given type of 'Applicative'
-- effects will be sequenced through a general 'Traversable' structure by its
-- 'traversable' and related methods, it is helpful to look more closely
-- at how a general 'traverse' method is implemented.  We'll look at how
-- general traversals are constructed primarily with a view to being able
-- to predict their behaviour as a user, even if you're not defining your
-- own 'Traversable' instances.
--
-- Traversable structures __@t a@__ are assembled incrementally from their
-- constituent parts, perhaps by prepending or appending individual elements of
-- type __@a@__, or, more generally, by recursively combining smaller composite
-- traversable building blocks that contain multiple such elements.
--
-- As in the [tree example](#tree) above, the components being combined are
-- typically pieced together by a suitable /constructor/, i.e. a function
-- taking two or more arguments that returns a composite value.
--
-- The 'traverse' method enriches simple incremental construction with
-- threading of 'Applicative' effects of some function __@g :: a -> f b@__.
--
-- The basic building blocks we'll use to model the construction of 'traverse'
-- are a hypothetical set of elementary functions, some of which may have
-- direct analogues in specific @Traversable@ structures.  For example, the
-- __@(':')@__ constructor is an analogue for lists of @prepend@ or the more
-- general @combine@.
--
-- > empty :: t a               -- build an empty container
-- > singleton :: a -> t a      -- build a one-element container
-- > prepend :: a -> t a -> t a -- extend by prepending a new initial element
-- > append  :: t a -> a -> t a -- extend by appending a new final element
-- > combine :: a1 -> a2 -> ... -> an -> t a -- combine multiple inputs
--
-- * An empty structure has no elements of type __@a@__, so there's nothing
--   to which __@g@__ can be applied, but since we need an output of type
--   __@f (t b)@__, we just use the 'pure' instance of __@f@__ to wrap an
--   empty of type __@t b@__:
--
--     > traverse _ (empty :: t a) = pure (empty :: t b)
--
--     With the List monad, /empty/ is __@[]@__, while with 'Maybe' it is
--     'Nothing'.  With __@Either e a@__ we have an /empty/ case for each
--     value of __@e@__:
--
--     > traverse _ (Left e :: Either e a) = pure $ (Left e :: Either e b)
--
-- * A singleton structure has just one element of type __@a@__, and
--   'traverse' can take that __@a@__, apply __@g :: a -> f b@__ getting an
--   __@f b@__, then __@fmap singleton@__ over that, getting an __@f (t b)@__
--   as required:
--
--     > traverse g (singleton a) = fmap singleton $ g a
--
--     Note that if __@f@__ is __@List@__ and __@g@__ returns multiple values
--     the result will be a list of multiple __@t b@__ singletons!
--
--     Since 'Maybe' and 'Either' are either empty or singletons, we have
--
--     > traverse _ Nothing = pure Nothing
--     > traverse g (Just a) = Just <$> g a
--
--     > traverse _ (Left e) = pure (Left e)
--     > traverse g (Right a) = Right <$> g a
--
--     For @List@, empty is __@[]@__ and @singleton@ is __@(:[])@__, so we have:
--
--     > traverse _ []  = pure []
--     > traverse g [a] = fmap (:[]) (g a)
--     >                = (:) <$> (g a) <*> traverse g []
--     >                = liftA2 (:) (g a) (traverse g [])
--
-- * When the structure is built by adding one more element via __@prepend@__
--   or __@append@__, traversal amounts to:
--
--     > traverse g (prepend a t0) = prepend <$> (g a) <*> traverse g t0
--     >                           = liftA2 prepend (g a) (traverse g t0)
--
--     > traverse g (append t0 a) = append <$> traverse g t0 <*> g a
--     >                          = liftA2 append (traverse g t0) (g a)
--
--     The origin of the combinatorial product when __@f@__ is @List@ should now
--     be apparent, when __@traverse g t0@__ has __@n@__ elements and __@g a@__
--     has __@m@__ elements, the /non-deterministic/ 'Applicative' instance of
--     @List@ will produce a result with __@m * n@__ elements.
--
-- * When combining larger building blocks, we again use __@('<*>')@__ to
--   combine the traversals of the components.  With bare elements __@a@__
--   mapped to __@f b@__ via __@g@__, and composite traversable
--   sub-structures transformed via __@traverse g@__:
--
--     > traverse g (combine a1 a2 ... an) =
--     >     combine <$> t1 <*> t2 <*> ... <*> tn
--     >   where
--     >      t1 = g a1          -- if a1 fills a slot of type @a@
--     >         = traverse g a1 -- if a1 is a traversable substructure
--     >      ... ditto for the remaining constructor arguments ...
--
-- The above definitions sequence the 'Applicative' effects of __@f@__ in the
-- expected order while producing results of the expected shape __@t@__.
--
-- For lists this becomes:
--
-- > traverse g [] = pure []
-- > traverse g (x:xs) = liftA2 (:) (g a) (traverse g xs)
--
-- The actual definition of 'traverse' for lists is an equivalent
-- right fold in order to facilitate list /fusion/.
--
-- > traverse g = foldr (\x r -> liftA2 (:) (g x) r) (pure [])

------------------

-- $advanced
--
-- #advanced#
-- In the sections below we'll examine some advanced choices of 'Applicative'
-- effects that give rise to very different transformations of @Traversable@
-- structures.
--
-- These examples cover the implementations of 'fmapDefault', 'foldMapDefault',
-- 'mapAccumL' and 'mapAccumR' functions illustrating the use of 'Identity',
-- 'Const' and stateful 'Applicative' effects.  The [ZipList](#ziplist) example
-- illustrates the use of a less-well known 'Applicative' instance for lists.
--
-- This is optional material, which is not essential to a basic understanding of
-- @Traversable@ structures.  If this is your first encounter with @Traversable@
-- structures, you can come back to these at a later date.

-- $coercion
--
-- #coercion#
-- Some of the examples make use of an advanced Haskell feature, namely
-- @newtype@ /coercion/.  This is done for two reasons:
--
-- * Use of 'coerce' makes it possible to avoid cluttering the code with
--   functions that wrap and unwrap /newtype/ terms, which at runtime are
--   indistinguishable from the underlying value.  Coercion is particularly
--   convenient when one would have to otherwise apply multiple newtype
--   constructors to function arguments, and then peel off multiple layers
--   of same from the function output.
--
-- * Use of 'coerce' can produce more efficient code, by reusing the original
--   value, rather than allocating space for a wrapped clone.
--
-- If you're not familiar with 'coerce', don't worry, it is just a shorthand
-- that, e.g., given:
--
-- > newtype Foo a = MkFoo { getFoo :: a }
-- > newtype Bar a = MkBar { getBar :: a }
-- > newtype Baz a = MkBaz { getBaz :: a }
-- > f :: Baz Int -> Bar (Foo String)
--
-- makes it possible to write:
--
-- > x :: Int -> String
-- > x = coerce f
--
-- instead of
--
-- > x = getFoo . getBar . f . MkBaz

------------------

-- $identity
--
-- #identity#
-- The simplest Applicative functor is 'Identity', which just wraps and unwraps
-- pure values and function application.  This allows us to define
-- 'fmapDefault':
--
-- > {-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
-- > import Data.Coercible (coerce)
-- >
-- > fmapDefault :: forall t a b. Traversable t => (a -> b) -> t a -> t b
-- > fmapDefault = coerce (traverse @t @Identity @a @b)
--
-- The use of [coercion](#coercion) avoids the need to explicitly wrap and
-- unwrap terms via 'Identity' and 'runIdentity'.
--
-- As noted in [Overview](#overview), 'fmapDefault' can only be used to define
-- the requisite 'Functor' instance of a 'Traversable' structure when the
-- 'traverse' method is explicitly implemented.  An infinite loop would result
-- if in addition 'traverse' were defined in terms of 'sequenceA' and 'fmap'.

------------------

-- $stateful
--
-- #stateful#
-- Applicative functors that thread a changing state through a computation are
-- an interesting use-case for 'traverse'.  The 'mapAccumL' and 'mapAccumR'
-- functions in this module are each defined in terms of such traversals.
--
-- We first define a simplified (not a monad transformer) version of
-- 'Control.Monad.Trans.State.State' that threads a state __@s@__ through a
-- chain of computations left to right.  Its @('<*>')@ operator passes the
-- input state first to its left argument, and then the resulting state is
-- passed to its right argument, which returns the final state.
--
-- > newtype StateL s a = StateL { runStateL :: s -> (s, a) }
-- >
-- > instance Functor (StateL s) where
-- >     fmap f (StateL kx) = StateL $ \ s ->
-- >         let (s', x) = kx s in (s', f x)
-- >
-- > instance Applicative (StateL s) where
-- >     pure a = StateL $ \s -> (s, a)
-- >     (StateL kf) <*> (StateL kx) = StateL $ \ s ->
-- >         let { (s',  f) = kf s
-- >             ; (s'', x) = kx s' } in (s'', f x)
-- >     liftA2 f (StateL kx) (StateL ky) = StateL $ \ s ->
-- >         let { (s',  x) = kx s
-- >             ; (s'', y) = ky s' } in (s'', f x y)
--
-- With @StateL@, we can define 'mapAccumL' as follows:
--
-- > {-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
-- > mapAccumL :: forall t s a b. Traversable t
-- >           => (s -> a -> (s, b)) -> s -> t a -> (s, t b)
-- > mapAccumL g s ts = coerce (traverse @t @(StateL s) @a @b) (flip g) ts s
--
-- The use of [coercion](#coercion) avoids the need to explicitly wrap and
-- unwrap __@newtype@__ terms.
--
-- The type of __@flip g@__ is coercible to __@a -> StateL b@__, which makes it
-- suitable for use with 'traverse'.  As part of the Applicative
-- [construction](#construction) of __@StateL (t b)@__ the state updates will
-- thread left-to-right along the sequence of elements of __@t a@__.
--
-- While 'mapAccumR' has a type signature identical to 'mapAccumL', it differs
-- in the expected order of evaluation of effects, which must take place
-- right-to-left.
--
-- For this we need a variant control structure @StateR@, which threads the
-- state right-to-left, by passing the input state to its right argument and
-- then using the resulting state as an input to its left argument:
--
-- > newtype StateR s a = StateR { runStateR :: s -> (s, a) }
-- >
-- > instance Functor (StateR s) where
-- >     fmap f (StateR kx) = StateR $ \s ->
-- >         let (s', x) = kx s in (s', f x)
-- >
-- > instance Applicative (StateR s) where
-- >     pure a = StateR $ \s -> (s, a)
-- >     (StateR kf) <*> (StateR kx) = StateR $ \ s ->
-- >         let { (s',  x) = kx s
-- >             ; (s'', f) = kf s' } in (s'', f x)
-- >     liftA2 f (StateR kx) (StateR ky) = StateR $ \ s ->
-- >         let { (s',  y) = ky s
-- >             ; (s'', x) = kx s' } in (s'', f x y)
--
-- With @StateR@, we can define 'mapAccumR' as follows:
--
-- > {-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
-- > mapAccumR :: forall t s a b. Traversable t
-- >           => (s -> a -> (s, b)) -> s -> t a -> (s, t b)
-- > mapAccumR g s0 ts = coerce (traverse @t @(StateR s) @a @b) (flip g) ts s0
--
-- The use of [coercion](#coercion) avoids the need to explicitly wrap and
-- unwrap __@newtype@__ terms.
--
-- Various stateful traversals can be constructed from 'mapAccumL' and
-- 'mapAccumR' for suitable choices of @g@, or built directly along similar
-- lines.

------------------

-- $phantom
--
-- #phantom#
-- The 'Const' Functor enables applications of 'traverse' that summarise the
-- input structure to an output value without constructing any output values
-- of the same type or shape.
--
-- As noted [above](#overview), the @Foldable@ superclass constraint is
-- justified by the fact that it is possible to construct 'foldMap', 'foldr',
-- etc., from 'traverse'.  The technique used is useful in its own right, and
-- is explored below.
--
-- A key feature of folds is that they can reduce the input structure to a
-- summary value. Often neither the input structure nor a mutated clone is
-- needed once the fold is computed, and through list fusion the input may not
-- even have been memory resident in its entirety at the same time.
--
-- The 'traverse' method does not at first seem to be a suitable building block
-- for folds, because its return value __@f (t b)@__ appears to retain mutated
-- copies of the input structure.  But the presence of __@t b@__ in the type
-- signature need not mean that terms of type __@t b@__ are actually embedded
-- in __@f (t b)@__.  The simplest way to elide the excess terms is by basing
-- the Applicative functor used with 'traverse' on 'Const'.
--
-- Not only does __@Const a b@__ hold just an __@a@__ value, with the __@b@__
-- parameter merely a /phantom/ type, but when __@m@__ has a 'Monoid' instance,
-- __@Const m@__ is an 'Applicative' functor:
--
-- > import Data.Coerce (coerce)
-- > newtype Const a b = Const { getConst :: a } deriving (Eq, Ord, Show) -- etc.
-- > instance Functor (Const m) where fmap = const coerce
-- > instance Monoid m => Applicative (Const m) where
-- >    pure _   = Const mempty
-- >    (<*>)    = coerce (mappend :: m -> m -> m)
-- >    liftA2 _ = coerce (mappend :: m -> m -> m)
--
-- The use of [coercion](#coercion) avoids the need to explicitly wrap and
-- unwrap __@newtype@__ terms.
--
-- We can therefore define a specialisation of 'traverse':
--
-- > {-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
-- > traverseC :: forall t a m. (Monoid m, Traversable t)
-- >           => (a -> Const m ()) -> t a -> Const m (t ())
-- > traverseC = traverse @t @(Const m) @a @()
--
-- For which the Applicative [construction](#construction) of 'traverse'
-- leads to:
--
-- prop> null ts ==> traverseC g ts = Const mempty
-- prop> traverseC g (prepend x xs) = Const (g x) <> traverseC g xs
--
-- In other words, this makes it possible to define:
--
-- > {-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
-- > foldMapDefault :: forall t a m. (Monoid m, Traversable t) => (a -> m) -> t a -> m
-- > foldMapDefault = coerce (traverse @t @(Const m) @a @())
--
-- Which is sufficient to define a 'Foldable' superclass instance:
--
-- The use of [coercion](#coercion) avoids the need to explicitly wrap and
-- unwrap __@newtype@__ terms.
--
-- > instance Traversable t => Foldable t where foldMap = foldMapDefault
--
-- It may however be instructive to also directly define candidate default
-- implementations of 'foldr' and 'foldl'', which take a bit more machinery
-- to construct:
--
-- > {-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
-- > import Data.Coerce (coerce)
-- > import Data.Functor.Const (Const(..))
-- > import Data.Semigroup (Dual(..), Endo(..))
-- > import GHC.Exts (oneShot)
-- >
-- > foldrDefault :: forall t a b. Traversable t
-- >              => (a -> b -> b) -> b -> t a -> b
-- > foldrDefault f z = \t ->
-- >     coerce (traverse @t @(Const (Endo b)) @a @()) f t z
-- >
-- > foldlDefault' :: forall t a b. Traversable t => (b -> a -> b) -> b -> t a -> b
-- > foldlDefault' f z = \t ->
-- >     coerce (traverse @t @(Const (Dual (Endo b))) @a @()) f' t z
-- >   where
-- >     f' :: a -> b -> b
-- >     f' a = oneShot $ \ b -> b `seq` f b a
--
-- In the above we're using the __@'Data.Monoid.Endo' b@__ 'Monoid' and its
-- 'Dual' to compose a sequence of __@b -> b@__ accumulator updates in either
-- left-to-right or right-to-left order.
--
-- The use of 'seq' in the definition of __@foldlDefault'@__ ensures strictness
-- in the accumulator.
--
-- The use of [coercion](#coercion) avoids the need to explicitly wrap and
-- unwrap __@newtype@__ terms.
--
-- The 'GHC.Exts.oneShot' function gives a hint to the compiler that aids in
-- correct optimisation of lambda terms that fire at most once (for each
-- element __@a@__) and so should not try to pre-compute and re-use
-- subexpressions that pay off only on repeated execution.  Otherwise, it is
-- just the identity function.

------------------

-- $ziplist
--
-- #ziplist#
-- As a warm-up for looking at the 'ZipList' 'Applicative' functor, we'll first
-- look at a simpler analogue.  First define a fixed width 2-element @Vec2@
-- type, whose 'Applicative' instance combines a pair of functions with a pair of
-- values by applying each function to the corresponding value slot:
--
-- > data Vec2 a = Vec2 a a
-- > instance Functor Vec2 where
-- >     fmap f (Vec2 a b) = Vec2 (f a) (f b)
-- > instance Applicative Vec2 where
-- >     pure x = Vec2 x x
-- >     liftA2 f (Vec2 a b) (Vec2 p q) = Vec2 (f a p) (f b q)
-- > instance Foldable Vec2 where
-- >     foldr f z (Vec2 a b) = f a (f b z)
-- >     foldMap f (Vec2 a b) = f a <> f b
-- > instance Traversable Vec2 where
-- >     traverse f (Vec2 a b) = Vec2 <$> f a <*> f b
--
-- Along with a similar definition for fixed width 3-element vectors:
--
-- > data Vec3 a = Vec3 a a a
-- > instance Functor Vec3 where
-- >     fmap f (Vec3 x y z) = Vec3 (f x) (f y) (f z)
-- > instance Applicative Vec3 where
-- >     pure x = Vec3 x x x
-- >     liftA2 f (Vec3 p q r) (Vec3 x y z) = Vec3 (f p x) (f q y) (f r z)
-- > instance Foldable Vec3 where
-- >     foldr f z (Vec3 a b c) = f a (f b (f c z))
-- >     foldMap f (Vec3 a b c) = f a <> f b <> f c
-- > instance Traversable Vec3 where
-- >     traverse f (Vec3 a b c) = Vec3 <$> f a <*> f b <*> f c
--
-- With the above definitions, @'sequenceA'@ (same as @'traverse' 'id'@) acts
-- as a /matrix transpose/ operation on @Vec2 (Vec3 Int)@ producing a
-- corresponding @Vec3 (Vec2 Int)@:
--
-- Let __@t = Vec2 (Vec3 1 2 3) (Vec3 4 5 6)@__ be our 'Traversable' structure,
-- and __@g = id :: Vec3 Int -> Vec3 Int@__ be the function used to traverse
-- __@t@__.  We then have:
--
-- > traverse g t = Vec2 <$> (Vec3 1 2 3) <*> (Vec3 4 5 6)
-- >              = Vec3 (Vec2 1 4) (Vec2 2 5) (Vec2 3 6)
--
-- This construction can be generalised from fixed width vectors to variable
-- length lists via 'Control.Applicative.ZipList'.  This gives a transpose
-- operation that works well for lists of equal length.  If some of the lists
-- are longer than others, they're truncated to the longest common length.
--
-- We've already looked at the standard 'Applicative' instance of @List@ for
-- which applying __@m@__ functions __@f1, f2, ..., fm@__ to __@n@__ input
-- values __@a1, a2, ..., an@__ produces __@m * n@__ outputs:
--
-- >>> :set -XTupleSections
-- >>> [("f1",), ("f2",), ("f3",)] <*> [1,2]
-- [("f1",1),("f1",2),("f2",1),("f2",2),("f3",1),("f3",2)]
--
-- There are however two more common ways to turn lists into 'Applicative'
-- control structures.  The first is via __@'Const' [a]@__, since lists are
-- monoids under concatenation, and we've already seen that __@'Const' m@__ is
-- an 'Applicative' functor when __@m@__ is a 'Monoid'.  The second, is based
-- on 'Data.List.zipWith', and is called 'Control.Applicative.ZipList':
--
-- > {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- > newtype ZipList a = ZipList { getZipList :: [a] }
-- >     deriving (Show, Eq, ..., Functor)
-- >
-- > instance Applicative ZipList where
-- >     liftA2 f (ZipList xs) (ZipList ys) = ZipList $ zipWith f xs ys
-- >     pure x = repeat x
--
-- The 'liftA2' definition is clear enough, instead of applying __@f@__ to each
-- pair __@(x, y)@__ drawn independently from the __@xs@__ and __@ys@__, only
-- corresponding pairs at each index in the two lists are used.
--
-- The definition of 'pure' may look surprising, but it is needed to ensure
-- that the instance is lawful:
--
-- prop> liftA2 f (pure x) ys == fmap (f x) ys
--
-- Since __@ys@__ can have any length, we need to provide an infinite supply
-- of __@x@__ values in __@pure x@__ in order to have a value to pair with
-- each element __@y@__.
--
-- When 'Control.Applicative.ZipList' is the 'Applicative' functor used in the
-- [construction](#construction) of a traversal, a ZipList holding a partially
-- built structure with __@m@__ elements is combined with a component holding
-- __@n@__ elements via 'zipWith', resulting in __@min m n@__ outputs!
--
-- Therefore 'traverse' with __@g :: a -> ZipList b@__ will produce a @ZipList@
-- of __@t b@__ structures whose element count is the minimum length of the
-- ZipLists __@g a@__ with __@a@__ ranging over the elements of __@t@__.  When
-- __@t@__ is empty, the length is infinite (as expected for a minimum of an
-- empty set).
--
-- If the structure __@t@__ holds values of type __@ZipList a@__, we can use
-- the identity function __@id :: ZipList a -> ZipList a@__ for the first
-- argument of 'traverse':
--
-- > traverse (id :: ZipList a -> ZipList a) :: t (ZipList a) -> ZipList (t a)
--
-- The number of elements in the output @ZipList@ will be the length of the
-- shortest @ZipList@ element of __@t@__.  Each output __@t a@__ will have the
-- /same shape/ as the input __@t (ZipList a)@__, i.e. will share its number of
-- elements.
--
-- If we think of the elements of __@t (ZipList a)@__ as its rows, and the
-- elements of each individual @ZipList@ as the columns of that row, we see
-- that our traversal implements a /transpose/ operation swapping the rows
-- and columns of __@t@__, after first truncating all the rows to the column
-- count of the shortest one.
--
-- Since in fact __@'traverse' id@__ is just 'sequenceA' the above boils down
-- to a rather concise definition of /transpose/, with [coercion](#coercion)
-- used to implicitly wrap and unwrap the @ZipList@ @newtype@ as needed, giving
-- a function that operates on a list of lists:
--
-- >>> :set -XScopedTypeVariables
-- >>> import Control.Applicative (ZipList(..))
-- >>> import Data.Coerce (coerce)
-- >>>
-- >>> :{
-- >>> let
-- >>>     transpose :: forall a. [[a]] -> [[a]]
-- >>>     transpose = coerce (sequenceA :: [ZipList a] -> ZipList [a])
-- >>> in transpose [[1,2,3],[4..],[7..]]
-- >>> :}
-- [[1,4,7],[2,5,8],[3,6,9]]
--
-- The use of [coercion](#coercion) avoids the need to explicitly wrap and
-- unwrap __@ZipList@__ terms.

------------------

-- $laws
--
-- #laws#
-- A definition of 'traverse' must satisfy the following laws:
--
-- [Naturality]
--   @t . 'traverse' f = 'traverse' (t . f)@
--   for every applicative transformation @t@
--
-- [Identity]
--   @'traverse' 'Identity' = 'Identity'@
--
-- [Composition]
--   @'traverse' ('Data.Functor.Compose.Compose' . 'fmap' g . f)
--     = 'Data.Functor.Compose.Compose' . 'fmap' ('traverse' g) . 'traverse' f@
--
-- A definition of 'sequenceA' must satisfy the following laws:
--
-- [Naturality]
--   @t . 'sequenceA' = 'sequenceA' . 'fmap' t@
--   for every applicative transformation @t@
--
-- [Identity]
--   @'sequenceA' . 'fmap' 'Identity' = 'Identity'@
--
-- [Composition]
--   @'sequenceA' . 'fmap' 'Data.Functor.Compose.Compose'
--     = 'Data.Functor.Compose.Compose' . 'fmap' 'sequenceA' . 'sequenceA'@
--
-- where an /applicative transformation/ is a function
--
-- @t :: (Applicative f, Applicative g) => f a -> g a@
--
-- preserving the 'Applicative' operations, i.e.
--
-- @
-- t ('pure' x) = 'pure' x
-- t (f '<*>' x) = t f '<*>' t x
-- @
--
-- and the identity functor 'Identity' and composition functors
-- 'Data.Functor.Compose.Compose' are from "Data.Functor.Identity" and
-- "Data.Functor.Compose".
--
-- A result of the naturality law is a purity law for 'traverse'
--
-- @'traverse' 'pure' = 'pure'@
--
-- The superclass instances should satisfy the following:
--
--  * In the 'Functor' instance, 'fmap' should be equivalent to traversal
--    with the identity applicative functor ('fmapDefault').
--
--  * In the 'Foldable' instance, 'Data.Foldable.foldMap' should be
--    equivalent to traversal with a constant applicative functor
--    ('foldMapDefault').
--
-- Note: the 'Functor' superclass means that (in GHC) Traversable structures
-- cannot impose any constraints on the element type.  A Haskell implementation
-- that supports constrained functors could make it possible to define
-- constrained @Traversable@ structures.

------------------

-- $also
--
--  * \"The Essence of the Iterator Pattern\",
--    by Jeremy Gibbons and Bruno Oliveira,
--    in /Mathematically-Structured Functional Programming/, 2006, online at
--    <http://www.cs.ox.ac.uk/people/jeremy.gibbons/publications/#iterator>.
--
--  * \"Applicative Programming with Effects\",
--    by Conor McBride and Ross Paterson,
--    /Journal of Functional Programming/ 18:1 (2008) 1-13, online at
--    <http://www.soi.city.ac.uk/~ross/papers/Applicative.html>.
--
--  * \"An Investigation of the Laws of Traversals\",
--    by Mauro Jaskelioff and Ondrej Rypacek,
--    in /Mathematically-Structured Functional Programming/, 2012, online at
--    <http://arxiv.org/pdf/1202.2919>.