-- 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. 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:
--
--
-- - rnfn bounds the forced evaluation by depth of
-- recursion.
-- - rnfp forces based on patterns (static or dynamic).
--
--
-- 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.
--
-- NOTE: Versions >=0.6 are substantially different from the
-- original (now deprecated) 0.5.* releases, particularly as regards
-- NFDataP.
@package deepseq-bounded
@version 0.7.0.2
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). Prefix
-- modifiers may be given in any order.
--
-- NOTE: The depth field in PatNodeAttrs is not really
-- an attribute, it is logically a (mandatory) extra parameter
-- to WN and TN nodes (and only those). (Whereas
-- attributes are all optional and node-type-agnostic.) The
-- depth is stored here as a convenient hack only!
-- Explanation becomes necessary since Haddock makes it visible
-- no matter what, I mention this, in case of confusion, because
-- the depth is always postfix, not prefix.
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). (This is not an attribute,
-- it's a displaced mandatory parameter, specific to these two node
-- types.)
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
instance Typeable Rose
instance Typeable PatNodeAttrs
instance Typeable PatNode
instance Show a => Show (Rose a)
instance Eq a => Eq (Rose a)
instance Show PatNodeAttrs
instance Eq PatNodeAttrs
instance Eq PatNode
instance Eq SeqNode
instance Ord SeqNode
instance Show PatNode
instance NFData PatNode
instance NFData PatNodeAttrs
instance NFData ThreadId
instance Functor Rose
instance NFData a => NFData (Rose 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. 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":
--
--
-- - Not More Specifc A subpattern (of a pattern) is never more
-- specific (i.e. less permissive), in terms of what values it
-- will match.
-- - Not More Forcing A subpattern never has greater forcing
-- potential.
--
--
-- 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.
--
-- 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:
--
--
-- - those corresponding to actual leaf (nullary) nodes of the
-- term
--
--
--
-- - interior nodes of the pattern corresponding to interior nodes of
-- the term
- these are Node WR chs where chs are
-- the child subpatterns of this interior pattern node
--
--
--
-- - leaf nodes of the pattern corresponding to interior nodes of the
-- term, that is, non-leaf nodes of the term which are at a depth
-- n of nested constructor applications.
- these are
-- Node WR chs' where chs' = map (const $ Node WI []) chs =
-- map (const emptyPat) chs
- this essentially says we're
-- allowed to know the arity of the node, but aside from this cardinal
-- number we know nothing whatsoever concerning the child subpatterns and
-- are not even permitted to evaluate their heads
--
--
-- All interior nodes are WR, and all leaf nodes are WI;
-- WS never arise.
--
-- 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.
--
-- 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):
--
--
-- - Not More Specifc Shrinkage is never towards a more specific
-- (i.e. less permissive) pattern.
-- - Not More Forcing Shrinkage is never towards a pattern with
-- greater forcing potential.
--
--
-- And additionally, for finite patterns only:
--
--
-- - Non-Constancy A finite pattern is constant under shrinkage
-- iff the pattern is trivial (emptyPat, ".", Node WI []).
-- However, infinite patterns have other limits. For instance, the
-- infinite pattern concat $ repeat "(." (yes you
-- can do that!) is already stationary under shrinkage.
-- - Convergence On iteration, shrinkage of finite patterns
-- reaches the trivial pattern in a number of steps proportional to the
-- size of the initial pattern argument. (Actually, *N and
-- *W nodes can make this larger.) However, in the case of
-- infinite patterns, all bets are off: Simple examples exist which
-- converge immediately, or which continue shrinking indefinitely.)
--
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
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.
showPat :: Pattern -> String
-- | 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
-- | 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 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.
--
--
-- - You can use the PatNode constructors directly.
-- - You can compile your patterns from strings in a concise embedded
-- language.
--
--
-- 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:
--
--
-- - has arity different than the number of subpatterns (only when
-- subpatterns given)
-- - has class/type/name not named in the constraint (only when
-- constraint given)
--
--
-- 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
instance Typeable DeepSeqBounded_PingException
instance Show DeepSeqBounded_PingException
instance (Typeable a, NFDataP a, Typeable b, NFDataP b, Typeable c, NFDataP c, Typeable d, NFDataP d, Typeable e, NFDataP e, Typeable f, NFDataP f, Typeable g, NFDataP g) => NFDataP (a, b, c, d, e, f, g)
instance (Typeable a, NFDataP a, Typeable b, NFDataP b, Typeable c, NFDataP c, Typeable d, NFDataP d, Typeable e, NFDataP e, Typeable f, NFDataP f) => NFDataP (a, b, c, d, e, f)
instance (Typeable a, NFDataP a, Typeable b, NFDataP b, Typeable c, NFDataP c, Typeable d, NFDataP d, Typeable e, NFDataP e) => NFDataP (a, b, c, d, e)
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
instance Exception DeepSeqBounded_PingException
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
-- | 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 -> ()
-- | 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
instance FF Pattern
instance FF Int
instance FF SeqNode