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

{-  LANGUAGE CPP #-}

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

-- |
-- Module      :  Control.DeepSeq.Bounded
-- Copyright   :  (c) 2014, Andrew G. Seniuk
-- License     :  BSD-style (see the file LICENSE)
-- 
-- Maintainer  :  Andrew Seniuk <rasfar@gmail.com>
-- Stability   :  provisional
-- Portability :  portable (but GHC for a few modules using generics)
--
-- We provide forcing functions which take a non-strict value
-- of a datatype, and force its evaluation in a pricipled way.
-- As with 'NFData', one should bear in mind the difference
-- between forcing and demand: in order for your forcing to
-- take effect, demand must be placed on the forcing function
-- itself by the course of execution.
--
-- A typical use of bounded forcing is to prevent resource leaks in
-- lazy streaming, by forcing chunks of data of bounded but sufficient
-- depth for the consumer to make progress.
--
-- Another use is to ensure any exceptions hidden within lazy
-- fields of a data structure do not leak outside the scope of the
-- exception handler; another is to force evaluation of a data structure in
-- one thread, before passing it to another thread (preventing work moving
-- to the wrong threads). Unlike "DeepSeq", potentially infinite coinductive
-- data types are supported by principled bounding of deep evaluation.
--
-- Refer to comments in the 'deepseq' package for more information on how
-- artificial forcing can be useful.
--
-- Recently, control (static or dynamic) of parallelisation has been added.
-- Control of evaluation order should also be possible (using 'pseq').

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

  module Control.DeepSeq.Bounded (

     -- * Forced evaluation to an arbitrary finite depth

#if 1
       module Control.DeepSeq.Bounded.NFDataN
#else
       NFDataN(..)
     , deepseqn, forcen
#endif

     -- * Forced evaluation over a pattern (arbitrary finite, or dynamic)

     , module Control.DeepSeq.Bounded.Pattern
     , module Control.DeepSeq.Bounded.PatAlg      -- re-exports the former
     , module Control.DeepSeq.Bounded.NFDataP     -- re-exports both
#if USE_SOP
     , module Control.DeepSeq.Bounded.NFDataPDyn  -- re-exps. all 3 above
#endif

     -- XXX On second thoughts, I don't want to depend on containers
     -- package just to provide a rose tree data type!...
     -- I don't export Data.Tree; ideally the API would never
     -- require the user to work at that low level, but if
     -- necessary they can import Data.Tree themselves.

     , Rose(..)

     -- * Forced evaluation "molecular style"

     , module Control.DeepSeq.Bounded.Seqable

     -- * Generic deriving support via "Generics.SOP"

#if USE_SOP
     , module Control.DeepSeq.Bounded.Generics.GSeqable
#endif

     , module Control.DeepSeq.Bounded.Generics.GNFDataN
#if USE_SOP
     , module Control.DeepSeq.Bounded.Generics.GNFDataP
#endif

#if USE_WW_DEEPSEQ
     -- * Re-exported

     , module Control.DeepSeq
#endif

  ) where

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

  import Control.DeepSeq.Bounded.Seqable

  import Control.DeepSeq.Bounded.NFDataN

  import Control.DeepSeq.Bounded.Pattern
  import Control.DeepSeq.Bounded.PatAlg
  import Control.DeepSeq.Bounded.NFDataP
#if USE_SOP
  import Control.DeepSeq.Bounded.NFDataPDyn
#endif

  -- In its own category, relative to GNFDataN and GNFDataP.
#if USE_SOP
  import Control.DeepSeq.Bounded.Generics.GSeqable
#endif

  import Control.DeepSeq.Bounded.Generics.GNFDataN
#if USE_SOP
  import Control.DeepSeq.Bounded.Generics.GNFDataP
#endif

#if USE_WW_DEEPSEQ
  import Control.DeepSeq
#endif

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