Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You're not alone. <code>seq</code> is probably one of the most difficult Haskell functions to use properly, for a few different reasons. In your first example:</p> <pre><code>foo s t = seq q (bar q t) where q = s*t </code></pre> <p><code>q</code> is evaluated before <code>bar q t</code> is evaluated. If <code>bar q t</code> is never evaluated, <code>q</code> won't be either. So if you have</p> <pre><code>main = do let val = foo 10 20 return () </code></pre> <p>as <code>val</code> is never used, it won't be evaluated. So <code>q</code> won't be evaluated either. If you instead have</p> <pre><code>main = print (foo 10 20) </code></pre> <p>the result of <code>foo 10 20</code> is evaluated (by <code>print</code>), so within <code>foo</code> <code>q</code> is evaluated before the result of <code>bar</code>.</p> <p>This is also why this doesn't work:</p> <pre><code>myseq x = seq x x </code></pre> <p>Semantically, this means the first <code>x</code> will be evaluated before the second <code>x</code> is evaluated. But if the second <code>x</code> is never evaluated, the first one doesn't need to be either. So <code>seq x x</code> is exactly equivalent to <code>x</code>.</p> <p>Your second example may or may not be the same thing. Here, the expression <code>s*t</code> will be evaluated before <code>bar</code>'s output, but it may not be the same <code>s*t</code> as the first parameter to <code>bar</code>. If the compiler performs common sub-expression elimination, it may common-up the two identical expressions. GHC can be fairly conservative about where it does CSE though, so you can't rely on this. If I define <code>bar q t = q*t</code> it does perform the CSE and evaluate <code>s*t</code> before using that value in bar. It may not do so for more complex expressions.</p> <p>You might also want to know what is meant by <em>strict evaluation</em>. <code>seq</code> evaluates the first argument to weak head normal form (WHNF), which for data types means unpacking the outermost constructor. Consider this:</p> <pre><code>baz xs y = seq xs (map (*y) xs) </code></pre> <p><code>xs</code> must be a list, because of <code>map</code>. When <code>seq</code> evaluates it, it will essentially transform the code into</p> <pre><code>case xs of [] -&gt; map (*y) xs (_:_) -&gt; map (*y) xs </code></pre> <p>This means it will determine if the list is empty or not, then return the second argument. Note that <em>none of the list values are evaluated</em>. So you can do this:</p> <pre><code>Prelude&gt; seq [undefined] 4 4 </code></pre> <p>but not this</p> <pre><code>Prelude&gt; seq undefined 5 *** Exception: Prelude.undefined </code></pre> <p>Whatever data type you use for <code>seq</code>s first argument, evaluating to WHNF will go far enough to figure out the constructor and no further. Unless the data type has components that are marked as strict with a bang pattern. Then all the strict fields will also be evaluated to WHNF.</p> <p>Edit: (thanks to Daniel Wagner for suggestion in comments)</p> <p>For functions, <code>seq</code> will evaluate the expression until the function "has a lambda showing", which means that it's ready for application. Here are some examples that might demonstrate what this means:</p> <pre><code>-- ok, lambda is outermost Prelude&gt; seq (\x -&gt; undefined) 'a' 'a' -- not ok. Because of the inner seq, `undefined` must be evaluated before -- the lambda is showing Prelude&gt; seq (seq undefined (\x -&gt; x)) 'b' *** Exception: Prelude.undefined </code></pre> <p>If you think of a lambda binding as a (built-in) data constructor, <code>seq</code> on functions is perfectly consistent with using it on data.</p> <p>Also, "lambda binding" subsumes all types of function definitions, whether defined by lambda notation or as a normal function.</p> <p>The <a href="http://www.haskell.org/haskellwiki/Seq">Controversy</a> section of the HaskellWiki's seq page has a little about some of the consequences of <code>seq</code> in relation to functions.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload