[commit: ghc] master: Clarify the documentation for 'evaluate' (de9a836)

git at git.haskell.org git at git.haskell.org
Tue Feb 10 14:01:50 UTC 2015


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/de9a836cd920722a4c28dcb464ff2c8d5905acb9/ghc

>---------------------------------------------------------------

commit de9a836cd920722a4c28dcb464ff2c8d5905acb9
Author: Roman Cheplyaka <roma at ro-che.info>
Date:   Mon Feb 9 13:44:03 2015 -0600

    Clarify the documentation for 'evaluate'
    
    Summary:
    See:
    
      https://www.haskell.org/pipermail/ghc-devs/2015-January/007900.html
      https://ghc.haskell.org/trac/ghc/ticket/5129#comment:17
    
    Reviewers: hvr, Mikolaj, austin
    
    Reviewed By: Mikolaj, austin
    
    Subscribers: ezyang, nomeata, thomie
    
    Differential Revision: https://phabricator.haskell.org/D615


>---------------------------------------------------------------

de9a836cd920722a4c28dcb464ff2c8d5905acb9
 libraries/base/GHC/IO.hs | 41 ++++++++++++++++++++++++++++++-----------
 1 file changed, 30 insertions(+), 11 deletions(-)

diff --git a/libraries/base/GHC/IO.hs b/libraries/base/GHC/IO.hs
index e9ac941..7dbd338 100644
--- a/libraries/base/GHC/IO.hs
+++ b/libraries/base/GHC/IO.hs
@@ -470,20 +470,39 @@ a `finally` sequel =
     _ <- sequel
     return r
 
--- | Forces its argument to be evaluated to weak head normal form when
--- the resultant 'IO' action is executed. It can be used to order
--- evaluation with respect to other 'IO' operations; its semantics are
--- given by
+-- | Evaluate the argument to weak head normal form.
 --
--- >   evaluate x `seq` y    ==>  y
--- >   evaluate x `catch` f  ==>  (return $! x) `catch` f
--- >   evaluate x >>= f      ==>  (return $! x) >>= f
+-- 'evaluate' is typically used to uncover any exceptions that a lazy value
+-- may contain, and possibly handle them.
 --
--- /Note:/ the first equation implies that @(evaluate x)@ is /not/ the
--- same as @(return $! x)@.  A correct definition is
+-- 'evaluate' only evaluates to /weak head normal form/. If deeper
+-- evaluation is needed, the @force@ function from @Control.DeepSeq@
+-- may be handy:
 --
--- >   evaluate x = (return $! x) >>= return
+-- > evaluate $ force x
 --
+-- There is a subtle difference between @'evaluate' x@ and @'return' '$!' x@,
+-- analogous to the difference between 'throwIO' and 'throw'. If the lazy
+-- value @x@ throws an exception, @'return' '$!' x@ will fail to return an
+-- 'IO' action and will throw an exception instead. @'evaluate' x@, on the
+-- other hand, always produces an 'IO' 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 at .
 evaluate :: a -> IO a
 evaluate a = IO $ \s -> seq# a s -- NB. see #2273, #5129
-



More information about the ghc-commits mailing list