-- 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: -- --
-- 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. -- --
-- 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