-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Bounded deepseq, including support for generic deriving -- -- This package provides methods for partially (or fully) evaluating data -- structures ("bounded deep evaluation"). -- -- More information is available on the project homepage. -- -- Quoting comments from the deepseq package: -- -- "Artificial forcing is often used for adding strictness to a -- program, e.g. in order to force pending exceptions, remove space -- leaks, or force lazy I/O to happen. It is also useful in parallel -- programs, to ensure work does not migrate to the wrong thread." -- -- Sometimes we don't want to, or cannot, force all the way. Any infinite -- recursive type is an example. Also, bounded forcing bridges the -- theoretical axis between shallow seq and full deepseq. -- -- We provide two new classes NFDataN and NFDataP. -- Instances of these provide bounded deep evaluation for arbitrary -- polytypic terms: -- --
-- showPat . compilePat patstring = patstring ---- -- provided that compilePat patstring succeeds. (And, -- only up to subpatterns elided from # (WI or TI) or from -- * (WW, WN, TW, TN, PW or PN) -- nodes.) showPat :: Pattern -> String data Rose a Node :: a -> [Rose a] -> Rose a data SeqNodeKind Insulate :: SeqNodeKind Propagate :: SeqNodeKind Spark :: SeqNodeKind instance Typeable Rose instance Typeable PatNode instance Show a => Show (Rose a) instance Eq a => Eq (Rose a) instance Generic (Rose a) instance Show PatNode instance Eq PatNode instance Generic PatNode instance Eq SeqNodeKind instance Ord SeqNodeKind instance Datatype D1Rose instance Constructor C1_0Rose instance Datatype D1PatNode instance Constructor C1_0PatNode instance Constructor C1_1PatNode instance Constructor C1_2PatNode instance Constructor C1_3PatNode instance Constructor C1_4PatNode instance Constructor C1_5PatNode instance Constructor C1_6PatNode instance Constructor C1_7PatNode instance Constructor C1_8PatNode instance Constructor C1_9PatNode instance Constructor C1_10PatNode instance Constructor C1_11PatNode instance NFData PatNode instance NFData a => NFData (Rose a) instance Functor Rose module Control.DeepSeq.Bounded.PatAlg -- | Compute the union of a list of Patterns. unionPats :: [Pattern] -> Pattern -- | Compute the intersection of a list of Patterns. -- -- XXX This doesn't yet handle type-constrained PatNodes -- (TI, TR, TN or TW). intersectPats :: [Pattern] -> Pattern -- | Return True if the first pattern matches the second (and -- False otherwise). -- -- Note that matching does not imply spanning. Equality (==) or -- flip isSubPatOf will work there, depending on -- your intentions. -- -- XXX This doesn't yet handle type-constrained PatNodes -- (TI, TR, TN or TW), because -- intersectPats doesn't. isSubPatOf :: Pattern -> Pattern -> Bool -- | Obtain a lazy pattern, matching the shape of an arbitrary term (value -- expression). Interior nodes will be WR, and leaves will be -- WS. -- -- Note this gives counter-intuitive results when used on Rose -- a. For example, a rose tree with a single node will have a 3-node -- /\ shape.) Formally, mkPat is not idempotent on -- Patterns, but rather grows without bound when iterated. This -- shouldn't be an issue in practise. mkPat :: Data d => d -> Pattern -- | Obtain a lazy pattern, matching the shape of an arbitrary term, but -- only down to at most depth n. Interior nodes will be -- WR. Leaf nodes will be WS if they were leaves in the -- host value; otherwise (i.e. if they are at depth n) they will -- be WR. -- -- Satisfies forcep . mkPatN n = forcen -- n. -- -- See caveat in the comment to mkPat. mkPatN :: Data d => Int -> d -> Pattern -- | Grow all leaves by one level within the shape of the provided value. growPat :: Data d => Pattern -> d -> Pattern -- | Given an integer depth and a pattern, truncate the pattern to extend -- to at most this requested depth. truncatePat :: Int -> Pattern -> Pattern -- | Elide all leaves which have no non-leaf sibling. We want the pattern -- to still match the same value, only less of it. Merely eliding all -- leaves would, in most cases, cause match failure, so we have to be a -- bit more subtle. There are some arbitrary decisions about the -- relaxation route through the lattice. (Refer to the source for -- details.) shrinkPat :: Pattern -> Pattern -- | Old version, for temporary compatibility of seqaid demo mode. shrinkPat_old :: Pattern -> Pattern -- | There is no Nil in the Pattern type, but a single WI node as -- empty pattern is a dependable way to assure the empty pattern never -- forces anything. emptyPat :: Pattern -- | This creates a new WR node, the common root. The argument -- patterns become the children of the root (order is preserved). liftPats :: [Pattern] -> Pattern -- | Introduce siblings at a node (interior or leaf) of the target. The -- first argument is target, the second is a path, and the third is a -- list of subpatterns for insertion, along with the indices of the child -- before which to insert. If this index is negative, it counts from the -- right. Indices are always relative to the original target as it was -- received. splicePats :: Pattern -> [Int] -> [(Int, Pattern)] -> Pattern -- | Elide siblings at a node (interior or leaf) of the target. The first -- argument is target, the second is a path, and the third is a list of -- child indices for elision. If this index is negative, it counts from -- the right. Indices are always relative to the original target as it -- was received. elidePats :: Pattern -> [Int] -> [Int] -> Pattern -- | Select a leaf at random, and elide it. In order to achieve fairness, -- the node probabilities are weighted by nodes in branch. The path arg -- can "focus" the stochastic erosion to only consider leaves beneath a -- given node. erodePat :: StdGen -> [Int] -> Pattern -> (Pattern, StdGen) -- | Generic function version of Seqable (via Generics.SOP). -- -- Probably, a GHC.Generics variant would also be possible. -- -- This metaboilerplate is standard for using the generic deriving -- facilities of Generics.SOP. Consider seqaid for a turnkey -- solution. -- --
-- {-# LANGUAGE TemplateHaskell #-}
-- {-# LANGUAGE DataKinds #-}
-- {-# LANGUAGE TypeFamilies #-}
-- {-# LANGUAGE DeriveDataTypeable #-}
--
-- import Generics.SOP.TH
-- import Control.DeepSeq.Bounded.Seqable
--
-- data TA = A1 TB TA | A2
-- data TB = B1 Int | B2 TA
--
-- deriveGeneric ''TA
-- deriveGeneric ''TB
--
-- main = return $! force_ Propagate (A1 (force_ Propagate (B2 undefined)) A2)
--
module Control.DeepSeq.Bounded.Generics.GSeqable
grnf_ :: Generic a => SeqNodeKind -> a -> ()
gseq_ :: Generic a => SeqNodeKind -> a -> b -> b
gforce_ :: Generic a => SeqNodeKind -> a -> a
-- | This module provides an overloaded function, deepseqn, for
-- partially (or fully) evaluating data structures to a given depth.
module Control.DeepSeq.Bounded.NFDataN
-- | deepseqn n x y evaluates x to depth n, before
-- returning y.
--
-- This is used when expression x also appears in y,
-- but mere evaluation of y does not force the embedded
-- x subexpression as deeply as we wish.
--
-- The name deepseqn is used to illustrate the relationship to
-- seq: where seq is shallow in the sense that it only
-- evaluates the top level of its argument, deepseqn n
-- traverses (evaluates) the entire top n levels of the data
-- structure.
--
-- A typical 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.
--
-- It is also useful for diagnostic purposes when trying to understand
-- and manipulate space/time trade-offs in lazy code, and as a less
-- indiscriminate substitute for deepseq.
--
-- Furthermore, deepseqn can sometimes a better solution than
-- using stict fields in your data structures, because the latter will
-- behave strictly everywhere that its constructors are used, instead of
-- just where its laziness is problematic.
--
-- There may be possible applications to the prevention of resource leaks
-- in lazy streaming, but I'm not certain.
deepseqn :: NFDataN a => Int -> a -> b -> b
-- | forcen is a variant of deepseqn that is useful in some
-- circumstances.
--
-- -- forcen n x = deepseqn n x x ---- -- forcen n x evaluates x to depth n, and then -- returns it. Recall that, in common with all Haskell functions, -- forcen only performs evaluation when upstream demand actually -- occurs, so essentially it turns shallow evaluation into -- depth-n evaluation. forcen :: NFDataN a => Int -> a -> a -- | A class of types that can be evaluated to arbitrary depth. class NFDataN a where rnfn n x | n <= 0 = () | otherwise = x `seq` () rnfn :: NFDataN a => Int -> a -> () instance (NFDataN a1, NFDataN a2, NFDataN a3, NFDataN a4, NFDataN a5, NFDataN a6, NFDataN a7, NFDataN a8, NFDataN a9) => NFDataN (a1, a2, a3, a4, a5, a6, a7, a8, a9) instance (NFDataN a1, NFDataN a2, NFDataN a3, NFDataN a4, NFDataN a5, NFDataN a6, NFDataN a7, NFDataN a8) => NFDataN (a1, a2, a3, a4, a5, a6, a7, a8) instance (NFDataN a1, NFDataN a2, NFDataN a3, NFDataN a4, NFDataN a5, NFDataN a6, NFDataN a7) => NFDataN (a1, a2, a3, a4, a5, a6, a7) instance (NFDataN a1, NFDataN a2, NFDataN a3, NFDataN a4, NFDataN a5, NFDataN a6) => NFDataN (a1, a2, a3, a4, a5, a6) instance (NFDataN a1, NFDataN a2, NFDataN a3, NFDataN a4, NFDataN a5) => NFDataN (a1, a2, a3, a4, a5) instance (NFDataN a, NFDataN b, NFDataN c, NFDataN d) => NFDataN (a, b, c, d) instance (NFDataN a, NFDataN b, NFDataN c) => NFDataN (a, b, c) instance (NFDataN a, NFDataN b) => NFDataN (a, b) instance (Ix a, NFDataN a, NFDataN b) => NFDataN (Array a b) instance NFDataN a => NFDataN [a] instance NFDataN Version instance (NFDataN a, NFDataN b) => NFDataN (Either a b) instance NFDataN a => NFDataN (Maybe a) instance (RealFloat a, NFDataN a) => NFDataN (Complex a) instance (Integral a, NFDataN a) => NFDataN (Ratio a) instance NFDataN (a -> b) instance NFDataN (Fixed a) instance NFDataN Word64 instance NFDataN Word32 instance NFDataN Word16 instance NFDataN Word8 instance NFDataN Int64 instance NFDataN Int32 instance NFDataN Int16 instance NFDataN Int8 instance NFDataN () instance NFDataN Bool instance NFDataN Char instance NFDataN Double instance NFDataN Float instance NFDataN Integer instance NFDataN Word instance NFDataN Int -- | This module provides an overloaded function, deepseqp, for -- partially (or fully) evaluating data structures to bounded depth via -- pattern matching on term shape, and on class, type, and constructor -- names. -- -- There are two ways to use this API. -- --
-- forcep pat x = x `deepseqp pat` x ---- -- forcep pat x evaluates x to the depth determined by -- pat, and then returns x. Note that forcep pat -- x only takes effect when the value of forcep pat x -- itself is demanded, so essentially it turns shallow evaluation into -- evaluation to arbitrary bounded depth. -- -- Composition fuses (see forcep_). forcep :: NFDataP a => String -> a -> a -- | Self-composition fuses via -- --
-- "deepseqp_/composition" -- forall p1 p2 x1 x2. -- (.) (deepseqp_ p2 x2) (deepseqp_ p1 x1) -- = deepseqp_ ( liftPats [p1, p2] ) (x1,x2) ---- -- (Other fusion rules, not yet documented, may also be in effect.) deepseqp_ :: NFDataP a => Pattern -> a -> b -> b -- | Self-composition fuses via -- --
-- "forcep_/composition" -- forall p1 p2 x. -- (.) (forcep_ p2) (forcep_ p1) x -- = forcep_ ( unionPats [p1, p2] ) x ---- -- (Other fusion rules, not yet documented, may also be in effect.) forcep_ :: NFDataP a => Pattern -> a -> a -- | A class of types that can be evaluated over an arbitrary finite -- pattern. class (Typeable a, NFDataN a, NFData a) => NFDataP a where rnfp (Node WI _) _ = () rnfp (Node (TR treps) chs) d = if elem td treps then d `seq` () else () where td = show $ typeRepTyCon $ typeOf d rnfp (Node (TI treps) chs) d = if elem td treps then () else d `seq` () where td = show $ typeRepTyCon $ typeOf d rnfp _ d = d `seq` () rnfp :: NFDataP a => Pattern -> a -> () instance (Typeable a1, NFDataP a1, Typeable a2, NFDataP a2, Typeable a3, NFDataP a3, Typeable a4, NFDataP a4, Typeable a5, NFDataP a5, Typeable a6, NFDataP a6, Typeable a7, NFDataP a7) => NFDataP (a1, a2, a3, a4, a5, a6, a7) instance (Typeable a1, NFDataP a1, Typeable a2, NFDataP a2, Typeable a3, NFDataP a3, Typeable a4, NFDataP a4, Typeable a5, NFDataP a5, Typeable a6, NFDataP a6) => NFDataP (a1, a2, a3, a4, a5, a6) instance (Typeable a1, NFDataP a1, Typeable a2, NFDataP a2, Typeable a3, NFDataP a3, Typeable a4, NFDataP a4, Typeable a5, NFDataP a5) => NFDataP (a1, a2, a3, a4, a5) instance (Typeable a, NFDataP a, Typeable b, NFDataP b, Typeable c, NFDataP c, Typeable d, NFDataP d) => NFDataP (a, b, c, d) instance (Typeable a, NFDataP a, Typeable b, NFDataP b, Typeable c, NFDataP c) => NFDataP (a, b, c) instance (Typeable a, NFDataP a, Typeable b, NFDataP b) => NFDataP (a, b) instance (Ix a, NFDataP a, NFDataP b) => NFDataP (Array a b) instance NFDataP a => NFDataP [a] instance NFDataP Version instance (NFDataP a, NFDataP b) => NFDataP (Either a b) instance NFDataP a => NFDataP (Maybe a) instance (RealFloat a, NFDataP a) => NFDataP (Complex a) instance (Integral a, NFDataP a) => NFDataP (Ratio a) instance (Typeable a, Typeable b) => NFDataP (a -> b) instance Typeable a => NFDataP (Fixed a) instance NFDataP Word64 instance NFDataP Word32 instance NFDataP Word16 instance NFDataP Word8 instance NFDataP Int64 instance NFDataP Int32 instance NFDataP Int16 instance NFDataP Int8 instance NFDataP () instance NFDataP Bool instance NFDataP Char instance NFDataP Double instance NFDataP Float instance NFDataP Integer instance NFDataP Word instance NFDataP Int module Control.DeepSeq.Bounded.NFDataPDyn -- | SOP/SYB hybrid dynamic rnfp. Takes a SYB GenericQ -- PatNode argument, which extends the pattern dynamically, -- depending on the type of the value node. rnfpDyn :: (Generic a, All2 Show (Code a), All2 NFData (Code a), All2 NFDataN (Code a), All2 NFDataP (Code a), All2 Data (Code a)) => (forall c. Data c => c -> PatNode) -> a -> () -- | SOP/SYB hybrid dynamic deepseqp. deepseqpDyn :: (Show a, NFDataP a, Generic a, Data a, All2 Show (Code a), All2 NFData (Code a), All2 NFDataN (Code a), All2 NFDataP (Code a), All2 Data (Code a)) => (forall c. Data c => c -> PatNode) -> a -> b -> b -- | SOP/SYB hybrid dynamic forcep. forcepDyn :: (Show a, NFDataP a, Generic a, Data a, All2 Show (Code a), All2 NFData (Code a), All2 NFDataN (Code a), All2 NFDataP (Code a), All2 Data (Code a)) => (forall c. Data c => c -> PatNode) -> a -> a -- | SOP-only dynamic rnfp. Takes an SOP generic function yielding -- PatNode, which extends the pattern dynamically, depending on -- the type of the value node. rnfpDyn' :: (Generic a, All2 Generic (Code a), All2 Show (Code a), All2 NFData (Code a), All2 NFDataN (Code a), All2 NFDataP (Code a)) => (forall c. Generic c => c -> PatNode) -> a -> () -- | SOP-only dynamic deepseqp. deepseqpDyn' :: (Show a, NFDataP a, Generic a, Data a, All2 Generic (Code a), All2 Show (Code a), All2 NFData (Code a), All2 NFDataN (Code a), All2 NFDataP (Code a)) => (forall c. Generic c => c -> PatNode) -> a -> b -> b -- | SOP-only dynamic forcep. forcepDyn' :: (Show a, NFDataP a, Generic a, Data a, All2 Generic (Code a), All2 Show (Code a), All2 NFData (Code a), All2 NFDataN (Code a), All2 NFDataP (Code a)) => (forall c. Generic c => c -> PatNode) -> a -> a -- | SOP/Typeable hybrid dynamic rnfp. Takes a SYB GenericQ -- PatNode argument, which extends the pattern dynamically, -- depending on the type of the value node. rnfpDyn'' :: (Generic a, All2 Show (Code a), All2 NFData (Code a), All2 NFDataN (Code a), All2 NFDataP (Code a)) => (forall c. Typeable c => c -> PatNode) -> a -> () -- | SOP/Typeable hybrid dynamic deepseqp. deepseqpDyn'' :: (Show a, NFDataP a, Generic a, Data a, All2 Show (Code a), All2 NFData (Code a), All2 NFDataN (Code a), All2 NFDataP (Code a)) => (forall c. Typeable c => c -> PatNode) -> a -> b -> b -- | SOP/Typeable hybrid dynamic forcep. forcepDyn'' :: (Show a, NFDataP a, Generic a, Data a, All2 Show (Code a), All2 NFData (Code a), All2 NFDataN (Code a), All2 NFDataP (Code a)) => (forall c. Typeable c => c -> PatNode) -> a -> a -- | Support for generic deriving (via Generics.SOP) of -- NFDataN instances. -- -- NFDataN does not have any superclasses. -- -- It is also possible to derive instances using Generics, which -- avoids SOP and TH, but if you plan to use NFDataP then SOP is -- required. (SOP can be used without TH if necessary; the interested -- reader is referred to SOP documentation.) -- -- This metaboilerplate is standard for using the generic deriving -- facilities of GHC.Generics and Generics.SOP. Consider seqaid -- for a turnkey solution. -- --
-- {-# LANGUAGE TemplateHaskell #-}
-- {-# LANGUAGE DataKinds #-}
-- {-# LANGUAGE TypeFamilies #-}
-- {-# LANGUAGE DeriveGeneric #-}
--
-- import Generics.SOP.TH
-- import Control.DeepSeq.Bounded ( NFDataN(..), grnfn )
-- import GHC.Generics ( Generic )
--
-- import Control.DeepSeq.Bounded ( forcen )
--
-- data TA = A1 TB TA | A2 deriving ( Generic )
-- instance NFDataN TA where rnfn = grnfn
--
-- data TB = B1 Int | B2 TA deriving ( Generic )
-- instance NFDataN TB where rnfn = grnfn
--
-- deriveGeneric ''TA
-- deriveGeneric ''TB
--
-- main = return $! forcen 3 (A1 (B2 undefined) A2)
--
module Control.DeepSeq.Bounded.Generics.GNFDataN
grnfn :: (Generic a, All2 NFDataN (Code a)) => Int -> a -> ()
-- | Support for generic deriving (via Generics.SOP) of
-- NFDataP instances.
--
-- Note that NFDataP has superclasses NFDataN,
-- NFData and Typeable.
--
-- This metaboilerplate is standard for using the generic deriving
-- facilities of GHC.Generics and Generics.SOP. Consider seqaid
-- for a turnkey solution.
--
--
-- {-# LANGUAGE TemplateHaskell #-}
-- {-# LANGUAGE DataKinds #-}
-- {-# LANGUAGE TypeFamilies #-}
-- {-# LANGUAGE DeriveGeneric #-}
-- {-# LANGUAGE DeriveDataTypeable #-}
--
-- import Generics.SOP.TH
-- import Control.DeepSeq.Bounded ( NFDataP(..), grnfp )
-- import Control.DeepSeq.Bounded ( NFDataN(..), grnfn )
-- import Control.DeepSeq.Generics ( NFData(..), genericRnf )
-- import GHC.Generics ( Generic ) -- for deriving NFData
-- import Data.Typeable ( Typeable ) -- for name-constrained pattern nodes
--
-- import Control.DeepSeq.Bounded ( forcep )
--
-- data TA = A1 TB TA | A2 deriving ( Generic, Typeable )
-- instance NFData TA where rnf = genericRnf
-- instance NFDataN TA where rnfn = grnfn
-- instance NFDataP TA where rnfp = grnfp
--
-- data TB = B1 Int | B2 TA deriving ( Generic, Typeable )
-- instance NFData TB where rnf = genericRnf
-- instance NFDataN TB where rnfn = grnfn
-- instance NFDataP TB where rnfp = grnfp
--
-- deriveGeneric ''TA
-- deriveGeneric ''TB
--
-- main = return $! forcep ".{.{.}.}" (A1 (B2 undefined) A2)
--
module Control.DeepSeq.Bounded.Generics.GNFDataP
grnfp :: (Generic a, HasDatatypeInfo a, All2 NFDataP (Code a), NFDataP a) => Pattern -> a -> ()
-- | Support for generic deriving (via Generics.SOP) of
-- NFDataN and NFDataP instances.
--
-- This metaboilerplate is standard for using the generic deriving
-- facilities of GHC.Generics and Generics.SOP. Consider seqaid
-- for a turnkey solution.
--
--
-- {-# LANGUAGE TemplateHaskell #-}
-- {-# LANGUAGE DataKinds #-}
-- {-# LANGUAGE TypeFamilies #-}
-- {-# LANGUAGE DeriveGeneric #-}
-- {-# LANGUAGE DeriveDataTypeable #-}
--
-- import Generics.SOP.TH
-- import Control.DeepSeq.Bounded ( NFDataN(..), grnfn, NFDataP(..), grnfp )
-- import Control.DeepSeq.Generics ( NFData(..), genericRnf )
-- import GHC.Generics ( Generic ) -- for deriving NFData
-- import Data.Typeable ( Typeable ) -- for name-constrained pattern nodes
-- import Control.DeepSeq.Bounded ( forcen, forcep )
--
-- data TA = A1 TB TA | A2 deriving ( Generic, Typeable )
-- instance NFData TA where rnf = genericRnf
-- instance NFDataN TA where rnfn = grnfn
-- instance NFDataP TA where rnfp = grnfp
--
-- data TB = B1 Int | B2 TA deriving ( Generic, Typeable )
-- instance NFData TB where rnf = genericRnf
-- instance NFDataN TB where rnfn = grnfn
-- instance NFDataP TB where rnfp = grnfp
--
-- deriveGeneric ''TA
-- deriveGeneric ''TB
--
-- main = mainP
-- mainN = return $! forcen 3 (A1 (B2 undefined) A2) :: IO TA
-- mainP = return $! forcep ".{.{.}.}" (A1 (B2 undefined) A2) :: IO TA
-- mainS = return $! force_ Propagate (A1 (force_ Propagate (B2 undefined)) A2) :: IO TA
--
module Control.DeepSeq.Bounded.Generics
grnf_ :: Generic a => SeqNodeKind -> a -> ()
gseq_ :: Generic a => SeqNodeKind -> a -> b -> b
gforce_ :: Generic a => SeqNodeKind -> a -> a
grnfn :: (Generic a, All2 NFDataN (Code a)) => Int -> a -> ()
grnfp :: (Generic a, HasDatatypeInfo a, All2 NFDataP (Code a), NFDataP a) => Pattern -> a -> ()
-- | This module provides an overloaded function, seq_, for
-- efficiently switching between forcen 0 and
-- forcen 2. This is useful for connecting units of
-- forcing (propagating demand). It was motivated for use with
-- auto-instrumentation, where seq_ can be injected at every node
-- of the AST (refer to the seqaid project). Each node carries a
-- couple bits of information, determining which depth (0 or 2) is in
-- force, and whether to spark parallel evaluation when the depth is 2.
-- This state can be configured statically or dynamically.
module Control.DeepSeq.Bounded.Seqable
rnf_ :: Generic a => SeqNodeKind -> a -> ()
force_ :: Generic a => SeqNodeKind -> a -> a
seq_ :: Generic a => SeqNodeKind -> a -> b -> b
data SeqNodeKind
Insulate :: SeqNodeKind
Propagate :: SeqNodeKind
Spark :: SeqNodeKind
-- | 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
data Rose a
Node :: a -> [Rose a] -> Rose a