-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Bounded deepseq, including support for generic deriving -- -- NOTE: Version 0.6.* is a transitional version. Please refer to -- this page for details about what has changed since 0.5.5, -- and what's in store when bump 0.6 to 0.7. -- -- This package provides methods for partially (or fully) evaluating data -- structures ("bounded deep evaluation"). -- -- More information is available on the project homepage. There -- may be activity on this reddit discussion, where your comments -- are invited. -- -- Quoting 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 IO 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, for instance -- when dealing with potentially infinite values of coinductive types. -- 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: -- -- -- -- Instances of NFDataN and NFDataP can be automatically -- derived via Generics.SOP, backed by the GNFDataN and -- GNFDataP modules. NFDataN can optionally be derived by -- the standard GHC.Generics facility (but not so for -- NFDataP). -- -- Another approach is Seqable, which is similar to -- NFDataN, but optimised for use as a dynamically-reconfigurable -- forcing harness in the seqaid auto-instrumentation tool. -- -- Recent developments supporting parallelisation control (in -- Pattern and Seqable modules) may justify renaming this -- library to something which encompasses both strictness and parallelism -- aspects. @package deepseq-bounded @version 0.6.0.3 module Control.DeepSeq.Bounded.Pattern type Pattern = Rose PatNode -- | Only WR and TR allow for explicit recursion. -- -- All other PatNode values are in leaf position when they occur. -- -- Concrete syntax for W* and T* nodes are identical. A -- T* node is simply a W* node bearing a type -- constraint attribute. Please refer to the Grammar further down -- this page for more details, and links to even more information. -- -- Notes: -- -- I've kept the T* types broken out as separate -- constructors, although they could be handled as special cases of -- W* types in a way analogous to doSpark -- (PatNodeAttrs). These were not "absorbed" because the semantics -- seems icky, and it's still not clear which W* types even make -- sense with a type constraint... -- -- I tried parametrising this, but it messed up my Show instance and -- seemed to be pulling me away from Haskell 98, so reverted. It looks a -- bit ugly in the Haddock unfortunately, with the redundant column of -- PatNodeAttrs. The T* nodes will be absorbed by -- PatNodeAttrs in version 0.7, and it won't look so bad. data PatNode -- | (Insulate, . ) Don't even unwrap the constructor -- of this node. WI :: !PatNodeAttrs -> PatNode -- | (Recurse, (...) ) Continue pattern -- matching descendants, provided that arity is compatible (else the -- match fails). Interior nodes of a pattern are always WR, -- i.e. WR is the only PatNode offering explicit -- recursion. The rest (?S, ?N, and ?W) are -- implicitly recursive, but control is only as powerful as -- NFDataN. WR :: !PatNodeAttrs -> PatNode -- | (Stop, ! ) Stop recursing (nothing more forced -- down this branch). This is equivalent to WN at a depth -- of 1. WS is somewhat vestigial, and may be removed in -- 0.7. WS :: !PatNodeAttrs -> PatNode -- | (N (depth), *n ) rnfn n the -- branch under this node. WN :: !PatNodeAttrs -> PatNode -- | (Wild, * ) Fully force (rnf) the whole -- branch under this node. Note that this is not achievable as -- a limiting case of WN, so the existence of WW is -- formally justifiable in a way that WS is not. Having said that, -- for all practical purposes, a WN with depth = -- maxBound::Int could be used for WW... WW :: !PatNodeAttrs -> PatNode -- | Don't even unwrap the constructor of this node, if it's type is in the -- list; otherwise behave as WW. (Note this behaviour is the -- complement of TW behaviour.) TI :: !PatNodeAttrs -> PatNode -- | Match any of the types in the list (and continue pattern matching -- descendants); behave as WI for nodes of type not in the list. TR :: !PatNodeAttrs -> PatNode -- | rnfn n the branch under this node, if the node type -- matches any of the types in the list; otherwise behave as WI. TN :: !PatNodeAttrs -> PatNode -- | Fully force (rnf) the whole branch under this node, if the node -- type matches any of the types in the list; otherwise behave as -- WI. (Note this behaviour is the complement of TI -- behaviour.) TW :: !PatNodeAttrs -> PatNode -- | Dummy node type reserved for internal use. XX :: PatNode -- | These attributes can be mixed freely. Certain combinations may seem -- unuseful, but nothing is prohibited by design. -- -- While this may seem bloated, most of these capabilities can be truly -- banished from the code via build flags (USE_PAR_PATNODE etc.). -- -- In the concrete pattern syntax, all attributes are represented as -- prefix modifiers (prefixing the '.', '!', -- '(' or '*' pattern node designator), except for -- depth and typeConstraints, which are postfix. Prefix -- modifiers may be given in any order, but the postfix must be in -- depth-then-type-constraints order when both are present. data PatNodeAttrs PatNodeAttrs :: !Int -> !Int -> !Bool -> ![String] -> !Bool -> !Int -> !Bool -> !Bool -> Maybe [Int] -> !Bool -> !Bool -> Maybe ThreadId -> !Bool -> !Bool -> !Int -> !Int -> !Int -> PatNodeAttrs -- | Optional for convenience; set up with -- setPatternPatNodeUniqueIDs. Beware that this function is not -- called automatically (or if it happens to be at the moment, this -- behaviour shouldn't be relied upon). For example, if you were to call -- growPat, the added nodes would all have "uniqueID" of 0. uniqueID :: PatNodeAttrs -> !Int -- | (*n) Depth of forcing for WN and TN nodes -- (n is decimal integer depth). depth :: PatNodeAttrs -> !Int -- | (:) Constrain pattern to match only types named in -- typeConstraints. XXX This should be considered -- experimental still in 0.6. This and the NFDataPDyn aspects lost -- attention to seqaid. doConstrainType :: PatNodeAttrs -> !Bool -- | The list of type rep strings used in the type constraint (when -- doConstrainType is True). typeConstraints :: PatNodeAttrs -> ![String] -- | (@) Delay (current thread) for delayus microseconds. -- XXX Still buggy? doDelay :: PatNodeAttrs -> !Bool -- | Microseconds of delay (when doDelay is True). delayus :: PatNodeAttrs -> !Int -- | (=) Spark matching for parallel evaluation. doSpark :: PatNodeAttrs -> !Bool -- | (>perm) Sequence child subpattern matching, according -- to the permutation in pseqPerm. doPseq :: PatNodeAttrs -> !Bool -- | Lowercase alphabetic sequence is used in the concrete pattern syntax. -- >cdba(wxyz) will cause subpattern matching -- recursion on a quaternary constructor, with the subpattern -- computations sequenced y then z then -- x then w (order corresponds to -- cdba). pseqPerm :: PatNodeAttrs -> Maybe [Int] -- | (+) Output a traceline to stderr. doTrace :: PatNodeAttrs -> !Bool -- | (^) Raise informative (asynchronous? support is not strong for -- it, throwTo blocks...) exception en passant, for benefit -- of upstream. The exception is thrown in a new thread, so that the -- pattern matching continues; for a terminating version, see -- doDie. doPing :: PatNodeAttrs -> !Bool -- | Needed as argument for throwTo call. pingParentTID :: PatNodeAttrs -> Maybe ThreadId -- | (/) Kill (just this) thread. doDie :: PatNodeAttrs -> !Bool -- | (%) Note time passed since pattern-matched parent node. -- XXX Work in progress. doTiming :: PatNodeAttrs -> !Bool timestamp :: PatNodeAttrs -> !Int parent_timestamp :: PatNodeAttrs -> !Int delta_timestamp :: PatNodeAttrs -> !Int isWI :: PatNode -> Bool isWR :: PatNode -> Bool isWS :: PatNode -> Bool isWN :: PatNode -> Bool isWW :: PatNode -> Bool isTI :: PatNode -> Bool isTR :: PatNode -> Bool isTN :: PatNode -> Bool isTW :: PatNode -> Bool emptyPatNodeAttrs :: PatNodeAttrs getPatNodeAttrs :: PatNode -> PatNodeAttrs setPatNodeAttrs :: PatNode -> PatNodeAttrs -> PatNode setPatNodePingParentTID :: ThreadId -> PatNode -> PatNode showPerm :: Maybe [Int] -> String showPatRaw :: Pattern -> String showPatNodeRaw :: PatNode -> String setPatternPatNodeUniqueIDs :: Int -> Pattern -> Pattern data Rose a Node :: a -> [Rose a] -> Rose a data SeqNode Insulate :: SeqNode Propagate :: SeqNode Spark :: SeqNode -- | 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 #-}
--   {-# LANGUAGE GADTs #-}  -- for GHC < 7.8 (== 7.6.3)
--   
--   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.Generic.GSeqable grnf_ :: Generic a => SeqNode -> a -> () gseq_ :: Generic a => SeqNode -> a -> b -> b gforce_ :: Generic a => SeqNode -> a -> a -- | seqharn x is semantically the same as x, -- except its strictness, parallellism, etc. can be tweaked -- dynamically... -- --
--   seqharn = to . hliftA (gforce_ Insulate) . from
--   
-- -- I can see how this would be useful at compile-time, but how can we -- use this if seqharn only runs post-compilation? Or is it just -- analogous to forcep?... -- -- Also: How exactly to dynamically configure this?... seqharn :: Generic a => a -> a module Control.DeepSeq.Bounded.PatUtil -- | Compute the union of a list of Patterns. -- -- Note that unionPats is undefined when homologous nodes specify -- incompatible arities (only possible when WR or TR are -- involved). -- -- XXX Support for the various attributes is work in progress. -- It may be impossible to arrive at a consistent treatment for all -- attributes under unions. At the last moment, 0.6.0.0 will not -- be supporting type constraints under union, intersection or testing -- subpattern predicate. This is work in progress, but the five -- un-modified W* node types should be safe. unionPats :: [Pattern] -> Pattern -- | Compute the intersection of a list of Patterns. -- -- Where two (or more) homologous WR nodes disagree in arity, the -- intersection at that position becomes WI. -- -- XXX This doesn't yet handle type-constrained PatNodes -- (TI, TR, TN or TW). Other attributes are -- handled in a haphazard fashion. This is work in progress, but the five -- un-modified W* node types should be safe. intersectPats :: [Pattern] -> Pattern -- | Return True if the first pattern matches the second (and -- False otherwise). -- -- Arities must correspond (or the second pattern's node must be wild) -- for the match to succeed at each recursive PatNode -- (i.e. WR or TR). Matching does not imply -- spanning; flip subPat would work for that. -- -- XXX This doesn't yet handle type-constrained PatNodes -- (TI, TR, TN or TW), because -- intersectPats doesn't. Generally speaking, it is difficult to -- arrive at a good policy for subpattern, union and intersection, when -- mixed types of nodes with various attribute values are considered! -- Other attributes are handled in a haphazard fashion. This is work in -- progress, but the five un-modified W* node types should be -- safe. -- -- More formally, we have two "Subpattern Axioms": -- -- -- -- And a proper subpattern will always be strictly more permissive -- or less forcing (or both). subPat :: Pattern -> Pattern -> Bool -- | Obtain a lazy, potentially infinite pattern, matching the shape of an -- arbitrary term (value expression). -- -- There is only one kind of PatNode employed here, WR. -- (Note: This is an API breaking change from 0.5, where -- WS also occurred.) -- -- The Pattern is extended indefinitely on demand. In case the -- term has leaves, these will be WR nodes with empty child lists -- in the corresponding pattern. -- -- Caveat: Note that mkPat gives counter-intuitive -- results when used on rose trees, in particular on Pattern -- itself. 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, finite pattern, matching the shape of an arbitrary -- term, but only down to at most depth n. -- -- Satisfies forcep . mkPatN n = forcen -- n. (Later: I kinda doubt that is true in full generality?... -- Although it does convey the idea.) -- -- Unlike mkPat, three pattern node contexts arise here: -- -- -- -- -- -- -- -- All interior nodes are WR, and all leaf nodes are WI; -- WS never arise (which is a change from version 0.5). -- -- See caveat in the mkPat documentation. mkPatN :: Data d => Int -> d -> Pattern -- | Grow all leaves by one level within the shape of the provided value. -- This is intended to be used with "plain" patterns, i.e. those -- containing only WR and WI nodes. (There is no code -- enforcing this.) A new growth node always replaces a WI (leaf) -- node with a WR node bearing the suitable number of WI -- children to encode arity (see mkPat for general commentary -- about this). growPat :: Data d => Pattern -> d -> Pattern -- | Given an integer depth and a pattern, truncate the pattern to extend -- to at most this requested depth. -- -- Nodes in the truncated pattern which were WR and are now -- leaves, are changed to WI. (This is a change from 0.5, where -- they were changed to WS, which violates the Subpattern Axiom -- concerning forcing potential. It may be further changed to -- 'WR'-bearing-'WI'-children in 0.7, which preserves arity info, as is -- consistent with the new treatment of mkPatN in 0.6.) -- -- XXX Note that *N and *W nodes are -- retained, so if you are using those then "extend to at most this -- depth" does not mean the forcing potential of the pattern is at most -- that depth... It would be quite possible to improve this, so -- *N (and *W nodes, obviously) are "weakened" (depth -- is reduced) so that they end at the truncation depth, regardless of -- how far up they reside. In particular, any *N or *W -- node at truncation depth could be replaced by WS. This works -- well as all these node types are arity-agnostic. 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.) -- -- More formally, we have some "Shrinkage Axioms". The first two are -- really just the "Subpattern Axioms" again, that is, shrinkage is -- always to a subpattern in our sense of the word (see also -- subPat): -- -- -- -- And additionally, for finite patterns only: -- -- shrinkPat :: Pattern -> Pattern -- | There is no Nil in the Pattern type, but a single -- WI node as empty pattern is a dependable way to ensure that the -- empty pattern never forces anything. This sets PatNodeAttrs to -- emptyPatNodeAttrs. emptyPat :: Pattern -- | This creates a new WR node, the common root, with -- PatNodeAttrs set to emptyPatNodeAttrs. The argument -- patterns become the children of the root (order is preserved). liftPats :: [Pattern] -> Pattern -- | Add children to a node (interior or leaf) of the target. The first -- argument is target pattern, the second is a path (0-based indexing) -- from the root of the target to any choice node, and the third is a -- list of subpatterns for insertion, along with the indices of the -- insertion slots. Indices range through -1,0..n, where -- n is the number of existing children, and -1 is -- short for n (so you don't need to count off the children to -- append!). Indices are always relative to the original target as it was -- received. splicePats :: Pattern -> [Int] -> [(Int, Pattern)] -> Pattern -- | Elide children of a node (interior or leaf) of the target. The first -- argument is target pattern, the second is a path (0-based indexing) -- from the root of the target to any choice node, and the third is a -- list of child indices for elision. Indices range through -- -1,0..n-1, where n is the number of existing -- children, and -1 is short for n-1 (so you don't need -- to count off the children to elide the rightmost). 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) type Shape = Rose () shapeOf :: Data d => d -> Shape ghom :: Data d => GenericQ r -> d -> Rose r probDensRose :: Rose r -> Rose (r, Double) weightedRose :: Rose r -> Rose (r, Int) unzipRose :: Rose (r, s) -> (Rose r, Rose s) showRose :: Show r => Rose r -> String -- | This is normally part of Pattern, but is broken out for the -- transitional version 0.6.*. module Control.DeepSeq.Bounded.Compile compilePat :: String -> Pattern -- | Inverse of compilePat. -- --
--   showPat . compilePat patstring  =  patstring
--   
-- -- (up to optional whitespace, and canonical ordering of any attributes), -- provided that compilePat patstring succeeds. (And, only up -- to subpatterns elided from # (WI or TI) or from * -- (WW, WN, TW, or TN) nodes, in case these -- are still accepted by the parser!) showPat :: Pattern -> String -- | 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 values -- of 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 be 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. -- -- One of the special qualities of NFDataN is shape oblivity: it -- doesn't care about any details of the shape of the term it's forcing, -- it only cares about stratifying levels of recursion depth. (I would -- say "as contrasted with NFDataP" but cannot, because -- NFDataP was extended to include NFDataN -- syntax/capabilities, precisely to ammend this deficiency.) 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 generic functions rnf_, force_ and -- seq_, for efficient switching between n=0 and -- n=2 in the corresponding 'rnfn n', 'forcen n' and 'deepseqn -- n' (of NFDataN). 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 SeqNode carries a couple bits of information, determining -- which depth (0 or 2) is in effect, 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 => SeqNode -> a -> () force_ :: Generic a => SeqNode -> a -> a seq_ :: Generic a => SeqNode -> a -> b -> b data SeqNode Insulate :: SeqNode Propagate :: SeqNode Spark :: SeqNode -- | Support for generic deriving (via Generics.SOP) of -- NFDataN instances. -- -- NFDataN does not have any superclasses. -- -- It is also possible to derive instances using GHC.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 #-}
--   {-# LANGUAGE GADTs #-}  -- for GHC < 7.8 (== 7.6.3)
--   
--   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.Generic.GNFDataN grnfn :: (Generic a, All2 NFDataN (Code a)) => Int -> a -> () -- | 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. -- --
    --
  1. You can use the PatNode constructors directly.
  2. --
  3. You can compile your patterns from strings in a concise embedded -- language.
  4. --
-- -- There's no difference in expressive power, but use of the DSL is -- recommended, because the embedded Pattern compiler can catch -- some errors that GHC cannot (using PatNode constructors -- explicitly). Also, the pattern strings are easier to read and write. -- -- With some qualifications (concerning WI nodes, and -- PatNodeAttrs configuration), composition fuses, and what's -- more, it's commutative... -- -- Motivation -- -- 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 values -- of 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 an optimal -- substitute for deepseq (where "optimal" doesn't include -- changing the code to remove the need for artificial forcing!). -- -- deepseqp with optimal patterns is usually a better solution -- even than stict fields in your data structures, because the latter -- will behave strictly everywhere the 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. -- -- Semantics -- -- (For additional details, see Control.DeepSeq.Bounded.Pattern.) -- -- deepseqp and friends artifically force evaluation of a term so -- long as the pattern matches. -- -- A mismatch occurs at a pattern node when the corresponding constructor -- node either: -- -- -- -- A mismatch will cause evaluation down that branch to stop, but any -- upstream matching/forcing will continue uninterrupted. (This -- behaviour can now be changed with PatNodeAttrs, available since -- 0.6.) -- -- Note that patterns may extend beyond the values they match against, -- without incurring any mismatch. This semantics is not the only -- possible, but bear in mind that order of evaluation is -- nondeterministic, barring further measures. (This behaviour can -- also now be changed with PatNodeAttrs.) -- -- See also NFDataPDyn for another approach, which dynamically -- generates forcing patterns, and can depend on value info (in addition -- to type info). (These dynamic aspects never received the attention -- I intended to give them, I got so caught up in seqaid, which offers -- similar features. Hopefully actual use of these tools in the near -- future will give me some perspective on whether NFDataPDyn -- should get attention.) module Control.DeepSeq.Bounded.NFDataP -- | deepseqp evaluates the first argument to the extent specified -- by a Pattern, before returning the second. -- -- Quoting from the DeepSeq documentation (deepseq -- package): -- -- "deepseq can be useful for forcing pending exceptions, -- eradicating space leaks, or forcing lazy I/O to happen. It is also -- useful in conjunction with parallel Strategies (see the -- parallel package). -- -- There is no guarantee about the ordering of evaluation. The -- implementation may evaluate the components of the structure in any -- order or in parallel. To impose an actual order on evaluation, use -- pseq from Control.Parallel in the parallel -- package." deepseqp :: NFDataP a => String -> a -> b -> b -- | A variant of deepseqp that is sometimes convenient: -- --
--   forcep pat x = deepseqp pat x x   -- (cannot write x `deepseqp pat` x by analogy with x `deepseq` x)
--   
-- -- forcep pat x evaluates x to the depth determined by -- pat, and then returns x. Again from deepseq: -- "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 data DeepSeqBounded_PingException DeepSeqBounded_PingException :: String -> DeepSeqBounded_PingException -- | A class of types that can be evaluated over an arbitrary finite -- pattern. class (Typeable a, NFDataN a, NFData a) => NFDataP a where rnfp p x | handleAttrs p x == Node XX [] = undefined rnfp (Node (WI {}) _) _ = () rnfp (Node (TR as) chs) d = if elem td treps then d `seq` () else () where td = show $ typeRepTyCon $ typeOf d treps = typeConstraints as rnfp (Node (TI as) chs) d = if elem td treps then () else d `seq` () where td = show $ typeRepTyCon $ typeOf d treps = typeConstraints as rnfp (Node (TW as) chs) d = if elem td treps then d `seq` () else () where td = show $ typeRepTyCon $ typeOf d treps = typeConstraints as rnfp _ d = d `seq` () rnfp :: NFDataP a => Pattern -> a -> () handleAttrs :: Typeable d => Pattern -> d -> Pattern 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 a 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 -- 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 #-}
--   {-# LANGUAGE GADTs #-}  -- for GHC < 7.8 (== 7.6.3)
--   
--   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.Generic.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. Also, SOP -- generic functions implementing Seqable without a class and -- 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 #-}
--   {-# LANGUAGE GADTs #-}  -- for GHC < 7.8 (== 7.6.3)
--   
--   import Generics.SOP.TH
--   import Control.DeepSeq.Bounded ( NFDataN(..), grnfn, NFDataP(..), grnfp )
--   import Control.DeepSeq.Generic ( 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.Generic grnfn :: (Generic a, All2 NFDataN (Code a)) => Int -> a -> () grnfp :: (Generic a, HasDatatypeInfo a, All2 NFDataP (Code a), NFDataP a) => Pattern -> a -> () grnf_ :: Generic a => SeqNode -> a -> () gseq_ :: Generic a => SeqNode -> a -> b -> b gforce_ :: Generic a => SeqNode -> a -> a -- | 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. -- -- Artificial forcing is most commonly used to suppress space leak, but -- it has many uses besides. Another is to ensure that exceptions hidden -- within lazy fields of a data structure don't 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, a form of time -- leak). -- -- Unlike DeepSeq, potentially infinite values of 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 is also supported (via -- pseq). module Control.DeepSeq.Bounded data Rose a Node :: a -> [Rose a] -> Rose a class FF k where data family F k :: * -> * phi :: (FF k, Generic v, NFDataN v, NFDataP v) => k -> F k v -> v deepseq_bounded_flag__new_improved_pattern_grammar :: Bool instance FF Pattern instance FF Int instance FF SeqNode