#if__GLASGOW_HASKELL__>=703{-# LANGUAGE Safe #-}#endif------------------------------------------------------------------------------- |-- Module : Control.DeepSeq-- Copyright : (c) The University of Glasgow 2001-2009-- License : BSD-style (see the file LICENSE)-- -- Maintainer : libraries@haskell.org-- Stability : stable-- Portability : portable---- This module provides an overloaded function, 'deepseq', for fully-- evaluating data structures (that is, evaluating to \"Normal Form\").---- A typical use is to prevent resource leaks in lazy IO programs, by-- forcing all characters from a file to be read. For example:---- > import System.IO-- > import Control.DeepSeq-- > -- > main = do-- > h <- openFile "f" ReadMode-- > s <- hGetContents h-- > s `deepseq` hClose h-- > return s---- 'deepseq' differs from 'seq' as it traverses data structures deeply,-- for example, 'seq' will evaluate only to the first constructor in-- the list:---- > > [1,2,undefined] `seq` 3-- > 3---- While 'deepseq' will force evaluation of all the list elements:---- > > [1,2,undefined] `deepseq` 3-- > *** Exception: Prelude.undefined---- Another common use is to ensure any exceptions hidden within lazy-- fields of a data structure do not leak outside the scope of the-- exception handler, or to force evaluation of a data structure in one-- thread, before passing to another thread (preventing work moving to-- the wrong threads).--moduleControl.DeepSeq(deepseq,($!!),force,NFData(..),)whereimportData.IntimportData.WordimportData.RatioimportData.CompleximportData.ArrayimportData.FixedimportData.Versioninfixr0$!!-- | 'deepseq': fully evaluates the first argument, before returning the-- second.---- The name 'deepseq' 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, 'deepseq' traverses the entire data structure-- evaluating it completely.---- '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.--deepseq::NFDataa=>a->b->bdeepseqab=rnfa`seq`b-- | the deep analogue of '$!'. In the expression @f $!! x@, @x@ is-- fully evaluated before the function @f@ is applied to it.($!!)::(NFDataa)=>(a->b)->a->bf$!!x=x`deepseq`fx-- | a variant of 'deepseq' that is useful in some circumstances:---- > force x = x `deepseq` x---- @force x@ fully evaluates @x@, and then returns it. Note that-- @force x@ only performs evaluation when the value of @force x@-- itself is demanded, so essentially it turns shallow evaluation into-- deep evaluation.force::(NFDataa)=>a->aforcex=x`deepseq`x-- | A class of types that can be fully evaluated.classNFDataawhere-- | rnf should reduce its argument to normal form (that is, fully-- evaluate all sub-components), and then return '()'.-- -- The default implementation of 'rnf' is ---- > rnf a = a `seq` ()-- -- which may be convenient when defining instances for data types with-- no unevaluated fields (e.g. enumerations).rnf::a->()rnfa=a`seq`()instanceNFDataIntinstanceNFDataWordinstanceNFDataIntegerinstanceNFDataFloatinstanceNFDataDoubleinstanceNFDataCharinstanceNFDataBoolinstanceNFData()instanceNFDataInt8instanceNFDataInt16instanceNFDataInt32instanceNFDataInt64instanceNFDataWord8instanceNFDataWord16instanceNFDataWord32instanceNFDataWord64instanceNFData(Fixeda)-- |This instance is for convenience and consistency with 'seq'.-- This assumes that WHNF is equivalent to NF for functions.instanceNFData(a->b)--Rational and complex numbers.instance(Integrala,NFDataa)=>NFData(Ratioa)wherernfx=rnf(numeratorx,denominatorx)instance(RealFloata,NFDataa)=>NFData(Complexa)wherernf(x:+y)=rnfx`seq`rnfy`seq`()instanceNFDataa=>NFData(Maybea)wherernfNothing=()rnf(Justx)=rnfxinstance(NFDataa,NFDatab)=>NFData(Eitherab)wherernf(Leftx)=rnfxrnf(Righty)=rnfyinstanceNFDataData.Version.Versionwherernf(Data.Version.Versionbranchtags)=rnfbranch`seq`rnftagsinstanceNFDataa=>NFData[a]wherernf[]=()rnf(x:xs)=rnfx`seq`rnfxsinstance(Ixa,NFDataa,NFDatab)=>NFData(Arrayab)wherernfx=rnf(boundsx,Data.Array.elemsx)instance(NFDataa,NFDatab)=>NFData(a,b)wherernf(x,y)=rnfx`seq`rnfyinstance(NFDataa,NFDatab,NFDatac)=>NFData(a,b,c)wherernf(x,y,z)=rnfx`seq`rnfy`seq`rnfzinstance(NFDataa,NFDatab,NFDatac,NFDatad)=>NFData(a,b,c,d)wherernf(x1,x2,x3,x4)=rnfx1`seq`rnfx2`seq`rnfx3`seq`rnfx4instance(NFDataa1,NFDataa2,NFDataa3,NFDataa4,NFDataa5)=>NFData(a1,a2,a3,a4,a5)wherernf(x1,x2,x3,x4,x5)=rnfx1`seq`rnfx2`seq`rnfx3`seq`rnfx4`seq`rnfx5instance(NFDataa1,NFDataa2,NFDataa3,NFDataa4,NFDataa5,NFDataa6)=>NFData(a1,a2,a3,a4,a5,a6)wherernf(x1,x2,x3,x4,x5,x6)=rnfx1`seq`rnfx2`seq`rnfx3`seq`rnfx4`seq`rnfx5`seq`rnfx6instance(NFDataa1,NFDataa2,NFDataa3,NFDataa4,NFDataa5,NFDataa6,NFDataa7)=>NFData(a1,a2,a3,a4,a5,a6,a7)wherernf(x1,x2,x3,x4,x5,x6,x7)=rnfx1`seq`rnfx2`seq`rnfx3`seq`rnfx4`seq`rnfx5`seq`rnfx6`seq`rnfx7instance(NFDataa1,NFDataa2,NFDataa3,NFDataa4,NFDataa5,NFDataa6,NFDataa7,NFDataa8)=>NFData(a1,a2,a3,a4,a5,a6,a7,a8)wherernf(x1,x2,x3,x4,x5,x6,x7,x8)=rnfx1`seq`rnfx2`seq`rnfx3`seq`rnfx4`seq`rnfx5`seq`rnfx6`seq`rnfx7`seq`rnfx8instance(NFDataa1,NFDataa2,NFDataa3,NFDataa4,NFDataa5,NFDataa6,NFDataa7,NFDataa8,NFDataa9)=>NFData(a1,a2,a3,a4,a5,a6,a7,a8,a9)wherernf(x1,x2,x3,x4,x5,x6,x7,x8,x9)=rnfx1`seq`rnfx2`seq`rnfx3`seq`rnfx4`seq`rnfx5`seq`rnfx6`seq`rnfx7`seq`rnfx8`seq`rnfx9