| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Eval
Synopsis
- seq :: a -> b -> b
- lazy :: a -> a
- ($!) :: (a -> b) -> a -> b
- evaluate :: a -> IO a
- data NF a
- makeNF :: NFData a => a -> NF a
- getNF :: NF a -> a
- class NFData a where
- deepseq :: NFData a => a -> b -> b
- force :: NFData a => a -> a
- ($!!) :: NFData a => (a -> b) -> a -> b
- (<$!!>) :: (Monad m, NFData b) => (a -> b) -> m a -> m b
- rwhnf :: a -> ()
- class NFData1 (f :: * -> *) where
- rnf1 :: (NFData1 f, NFData a) => f a -> ()
- class NFData2 (p :: * -> * -> *) where
- rnf2 :: (NFData2 p, NFData a, NFData b) => p a b -> ()
- data Eval a
- runEval :: Eval a -> a
- type Strategy a = a -> Eval a
- using :: a -> Strategy a -> a
- withStrategy :: Strategy a -> a -> a
- dot :: Strategy a -> Strategy a -> Strategy a
- rseq :: Strategy a
- rdeepseq :: NFData a => Strategy a
- evalTraversable :: Traversable t => Strategy a -> Strategy (t a)
- evalList :: Strategy a -> Strategy [a]
- evalTuple2 :: Strategy a -> Strategy b -> Strategy (a, b)
- evalTuple3 :: Strategy a -> Strategy b -> Strategy c -> Strategy (a, b, c)
- evalTuple4 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy (a, b, c, d)
- evalTuple5 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy (a, b, c, d, e)
- evalTuple6 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy (a, b, c, d, e, f)
- evalTuple7 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy (a, b, c, d, e, f, g)
- evalTuple8 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy h -> Strategy (a, b, c, d, e, f, g, h)
- evalTuple9 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy h -> Strategy i -> Strategy (a, b, c, d, e, f, g, h, i)
Weak head normal form
The value of seq a b is bottom if a is bottom, and
otherwise equal to b. In other words, it evaluates the first
argument a to weak head normal form (WHNF). seq is usually
introduced to improve performance by avoiding unneeded laziness.
A note on evaluation order: the expression seq a b does
not guarantee that a will be evaluated before b.
The only guarantee given by seq is that the both a
and b will be evaluated before seq returns a value.
In particular, this means that b may be evaluated before
a. If you need to guarantee a specific order of evaluation,
you must use the function pseq from the "parallel" package.
The lazy function restrains strictness analysis a little. The
call lazy e means the same as e, but lazy has a magical
property so far as strictness analysis is concerned: it is lazy in
its first argument, even though its semantics is strict. After
strictness analysis has run, calls to lazy are inlined to be the
identity function.
This behaviour is occasionally useful when controlling evaluation
order. Notably, lazy is used in the library definition of
par:
par :: a -> b -> b par x y = case (par# x) of _ -> lazy y
If lazy were not lazy, par would look strict in y which
would defeat the whole purpose of par.
($!) :: (a -> b) -> a -> b infixr 0 #
Strict (call-by-value) application operator. It takes a function and an argument, evaluates the argument to weak head normal form (WHNF), then calls the function with that value.
Evaluate the argument to weak head normal form.
evaluate is typically used to uncover any exceptions that a lazy value
may contain, and possibly handle them.
evaluate only evaluates to weak head normal form. If deeper
evaluation is needed, the force function from Control.DeepSeq
may be handy:
evaluate $ force x
There is a subtle difference between and evaluate x,
analogous to the difference between return $! xthrowIO and throw. If the lazy
value x throws an exception, will fail to return an
return $! xIO action and will throw an exception instead. , on the
other hand, always produces an evaluate xIO action; that action will throw an
exception upon execution iff x throws an exception upon evaluation.
The practical implication of this difference is that due to the imprecise exceptions semantics,
(return $! error "foo") >> error "bar"
may throw either "foo" or "bar", depending on the optimizations
performed by the compiler. On the other hand,
evaluate (error "foo") >> error "bar"
is guaranteed to throw "foo".
The rule of thumb is to use evaluate to force or handle exceptions in
lazy values. If, on the other hand, you are forcing a lazy value for
efficiency reasons only and do not care about exceptions, you may
use .return $! x
Normal form
NF is an abstract data type representing data which has been
evaluated to normal form. Specifically, if a value of type
is in weak head normal form, then it is in reduced normal form;
alternatively, it is only necessary to NF aseq an to assure that
it is fully evaluated.NF a
Retrieves a from a value of type ; this value
is guaranteed to be in normal form.NF a
A class of types that can be fully evaluated.
Since: deepseq-1.1.0.0
Methods
rnf should reduce its argument to normal form (that is, fully
evaluate all sub-components), and then return '()'.
Generic NFData deriving
Starting with GHC 7.2, you can automatically derive instances
for types possessing a Generic instance.
Note: Generic1 can be auto-derived starting with GHC 7.4
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics (Generic, Generic1)
import Control.DeepSeq
data Foo a = Foo a String
deriving (Eq, Generic, Generic1)
instance NFData a => NFData (Foo a)
instance NFData1 Foo
data Colour = Red | Green | Blue
deriving Generic
instance NFData ColourStarting with GHC 7.10, the example above can be written more
concisely by enabling the new DeriveAnyClass extension:
{-# LANGUAGE DeriveGeneric, DeriveAnyClass #-}
import GHC.Generics (Generic)
import Control.DeepSeq
data Foo a = Foo a String
deriving (Eq, Generic, Generic1, NFData, NFData1)
data Colour = Red | Green | Blue
deriving (Generic, NFData)
Compatibility with previous deepseq versions
Prior to version 1.4.0.0, the default implementation of the rnf
method was defined as
rnfa =seqa ()
However, starting with deepseq-1.4.0.0, the default
implementation is based on DefaultSignatures allowing for
more accurate auto-derived NFData instances. If you need the
previously used exact default rnf method implementation
semantics, use
instance NFData Colour where rnf x = seq x ()
or alternatively
instance NFData Colour where rnf = rwhnf
or
{-# LANGUAGE BangPatterns #-}
instance NFData Colour where rnf !_ = ()Instances
deepseq :: NFData a => a -> b -> b #
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.
Since: deepseq-1.1.0.0
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 can be conveniently used in combination with ViewPatterns:
{-# LANGUAGE BangPatterns, ViewPatterns #-}
import Control.DeepSeq
someFun :: ComplexData -> SomeResult
someFun (force -> !arg) = {- 'arg' will be fully evaluated -}Another useful application is to combine force with
evaluate in order to force deep evaluation
relative to other IO operations:
import Control.Exception (evaluate)
import Control.DeepSeq
main = do
result <- evaluate $ force $ pureComputation
{- 'result' will be fully evaluated at this point -}
return ()Finally, here's an exception safe variant of the readFile' example:
readFile' :: FilePath -> IO String
readFile' fn = bracket (openFile fn ReadMode) hClose $ \h ->
evaluate . force =<< hGetContents hSince: deepseq-1.2.0.0
($!!) :: NFData a => (a -> b) -> a -> b infixr 0 #
the deep analogue of $!. In the expression f $!! x, x is
fully evaluated before the function f is applied to it.
Since: deepseq-1.2.0.0
(<$!!>) :: (Monad m, NFData b) => (a -> b) -> m a -> m b infixl 4 #
Deeply strict version of <$>.
Since: deepseq-1.4.3.0
class NFData1 (f :: * -> *) where #
A class of functors that can be fully evaluated.
Since: deepseq-1.4.3.0
Methods
Instances
| NFData1 [] | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Maybe | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Ratio | Available on Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Ptr | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 FunPtr | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 IORef | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Fixed | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Min | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Max | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 First | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Last | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 WrappedMonoid | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq Methods liftRnf :: (a -> ()) -> WrappedMonoid a -> () # | |
| NFData1 Option | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 StableName | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq Methods liftRnf :: (a -> ()) -> StableName a -> () # | |
| NFData1 ZipList | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Identity | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 First | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Last | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Dual | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Sum | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Product | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 Down | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 MVar | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 NonEmpty | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData a => NFData1 (Either a) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData a => NFData1 ((,) a) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData a => NFData1 (Array a) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData a => NFData1 (Arg a) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 (Proxy :: * -> *) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 (STRef s) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2) => NFData1 ((,,) a1 a2) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData a => NFData1 (Const a :: * -> *) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 ((:~:) a) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3) => NFData1 ((,,,) a1 a2 a3) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData1 f, NFData1 g) => NFData1 (Product f g) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData1 f, NFData1 g) => NFData1 (Sum f g) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData1 ((:~~:) a :: * -> *) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3, NFData a4) => NFData1 ((,,,,) a1 a2 a3 a4) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData1 f, NFData1 g) => NFData1 (Compose f g) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) => NFData1 ((,,,,,) a1 a2 a3 a4 a5) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) => NFData1 ((,,,,,,) a1 a2 a3 a4 a5 a6) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) => NFData1 ((,,,,,,,) a1 a2 a3 a4 a5 a6 a7) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8) => NFData1 ((,,,,,,,,) a1 a2 a3 a4 a5 a6 a7 a8) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
rnf1 :: (NFData1 f, NFData a) => f a -> () #
Lift the standard rnf function through the type constructor.
Since: deepseq-1.4.3.0
class NFData2 (p :: * -> * -> *) where #
A class of bifunctors that can be fully evaluated.
Since: deepseq-1.4.3.0
Minimal complete definition
Methods
Instances
| NFData2 Either | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData2 (,) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData2 Array | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData2 Arg | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData2 STRef | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData a1 => NFData2 ((,,) a1) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData2 (Const :: * -> * -> *) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData2 ((:~:) :: * -> * -> *) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2) => NFData2 ((,,,) a1 a2) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| NFData2 ((:~~:) :: * -> * -> *) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3) => NFData2 ((,,,,) a1 a2 a3) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3, NFData a4) => NFData2 ((,,,,,) a1 a2 a3 a4) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) => NFData2 ((,,,,,,) a1 a2 a3 a4 a5) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) => NFData2 ((,,,,,,,) a1 a2 a3 a4 a5 a6) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
| (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) => NFData2 ((,,,,,,,,) a1 a2 a3 a4 a5 a6 a7) | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
rnf2 :: (NFData2 p, NFData a, NFData b) => p a b -> () #
Lift the standard rnf function through the type constructor.
Since: deepseq-1.4.3.0
Evaluation strategies
Eval is a Monad that makes it easier to define parallel
strategies. It is a strict identity monad: that is, in
m >>= f
m is evaluated before the result is passed to f.
instance Monad Eval where
return = Done
m >>= k = case m of
Done x -> k xIf you wanted to construct a Strategy for a pair that sparked the
first component in parallel and then evaluated the second
component, you could write
myStrat :: Strategy (a,b)
myStrat (a,b) = do { a' <- rpar a; b' <- rseq b; return (a',b') }Alternatively, you could write this more compactly using the Applicative style as
myStrat (a,b) = (,) <$> rpar a <*> rseq b
Instances
| Monad Eval | |
| Functor Eval | |
| MonadFix Eval | |
Defined in Control.Parallel.Strategies | |
| Applicative Eval | |
type Strategy a = a -> Eval a #
A Strategy is a function that embodies a parallel evaluation strategy.
The function traverses (parts of) its argument, evaluating subexpressions
in parallel or in sequence.
A Strategy may do an arbitrary amount of evaluation of its
argument, but should not return a value different from the one it
was passed.
Parallel computations may be discarded by the runtime system if the
program no longer requires their result, which is why a Strategy
function returns a new value equivalent to the old value. The
intention is that the program applies the Strategy to a
structure, and then uses the returned value, discarding the old
value. This idiom is expressed by the using function.
using :: a -> Strategy a -> a infixl 0 #
Evaluate a value using the given Strategy.
x `using` s = runEval (s x)
withStrategy :: Strategy a -> a -> a #
dot :: Strategy a -> Strategy a -> Strategy a infixr 9 #
Compose two strategies sequentially. This is the analogue to function composition on strategies.
For any strategies strat1, strat2, and strat3,
(strat1 `dot` strat2) `dot` strat3 == strat1 `dot` (strat2 `dot` strat3) strat1 `dot` strat1 = strat1 strat1 `dot` r0 == strat1
strat2 `dot` strat1 == strat2 . withStrategy strat1
rseq evaluates its argument to weak head normal form.
rseq == evalSeq Control.Seq.rseq
rdeepseq :: NFData a => Strategy a #
rdeepseq fully evaluates its argument.
rdeepseq == evalSeq Control.Seq.rdeepseq
evalTraversable :: Traversable t => Strategy a -> Strategy (t a) #
Evaluate the elements of a traversable data structure according to the given strategy.
evalList :: Strategy a -> Strategy [a] #
Evaluate each element of a list according to the given strategy.
Equivalent to evalTraversable at the list type.
evalTuple2 :: Strategy a -> Strategy b -> Strategy (a, b) #
evalTuple5 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy (a, b, c, d, e) #
evalTuple6 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy (a, b, c, d, e, f) #
evalTuple7 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy (a, b, c, d, e, f, g) #