<div dir="ltr">seq forces the term into weak-head normal form. Basically just enough to tell whether the list is `[]` or not. It's the same kind of evaluation that would happen if you pattern matched on the constructor. Only one Char needs to be read in order to make that determination. Sometimes this is desirable, but other times you want to traverse the whole structure and make sure everything is forced. The confusion is made much worse because you're using lazy IO.<div><br></div><div>The `takeWhile (/= '\04')` is redundant here, the ^D never ends up in that string.</div><div><br></div><div>Most cases where you use `seq` rather than `deepseq` are because you know that the substructure is already evaluated, or there is no need to evaluate it, and it may be very inefficient to do that redundant work.</div><div><br></div><div>See also:</div><div><br></div><div>* <a href="http://chimera.labs.oreilly.com/books/1230000000929/ch02.html#sec_par-eval-whnf">http://chimera.labs.oreilly.com/books/1230000000929/ch02.html#sec_par-eval-whnf</a></div><div>* <a href="https://hackhands.com/lazy-evaluation-works-haskell/">https://hackhands.com/lazy-evaluation-works-haskell/</a></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jul 21, 2015 at 7:29 PM, Ryan Warner <span dir="ltr"><<a href="mailto:ryan.warner.mn+haskell@gmail.com" target="_blank">ryan.warner.mn+haskell@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div style="font-size:13px">I'm trying to grok Haskell's laziness. In this example, why does the seq not force youTyped to wait for s to be fully evaluated, before returning a result to putStrLn?</div><div style="font-size:13px"><br></div><div style="font-size:13px">--------------------</div><div style="font-size:13px">import System.IO (hSetBuffering,stdin,BufferMode(..))</div><div style="font-size:13px"><br></div><div style="font-size:13px">youTyped :: String -> String</div><div style="font-size:13px">youTyped s = s `seq` "you typed: " ++ s</div><div style="font-size:13px"><br></div><div style="font-size:13px">main = do</div><div style="font-size:13px"><span style="white-space:pre-wrap"> </span>hSetBuffering stdin NoBuffering</div><div style="font-size:13px"><span style="white-space:pre-wrap"> </span>s <- getContents</div><div style="font-size:13px"><span style="white-space:pre-wrap"> </span>let l = map youTyped $ lines $ takeWhile ( /= '\04' ) s</div><div style="font-size:13px"><span style="white-space:pre-wrap"> </span>mapM_ putStrLn ("Start Typing (Ctrl-D to exit):":l)</div><div style="font-size:13px">--------------------</div><div style="font-size:13px"><br></div><div style="font-size:13px">The output looks like:</div><div style="font-size:13px"><br></div><div style="font-size:13px"><div>--------------------</div><p style="margin:0px;font-size:11px;font-family:Menlo">$ runhaskell seqLazy.hs </p><p style="margin:0px;font-size:11px;font-family:Menlo">Start Typing (Ctrl-D to exit):</p><p style="margin:0px;font-size:11px;font-family:Menlo">Hyou typed: Heelllloo wwoorrlldd</p><p style="margin:0px;font-size:11px;font-family:Menlo;min-height:13px"><br></p><p style="margin:0px;font-size:11px;font-family:Menlo">fyou typed: faaiill</p><p style="margin:0px;font-size:11px;font-family:Menlo;min-height:13px"><br></p><p style="margin:0px;font-size:11px;font-family:Menlo">^D</p></div><div style="font-size:13px">--------------------</div><div style="font-size:13px"><br></div><div style="font-size:13px">Changing seq, to deepseq does the trick though.</div><div style="font-size:13px"><br></div><div style="font-size:13px"><div>--------------------</div><div>import System.IO (hSetBuffering,stdin,BufferMode(..))</div><div>import Control.DeepSeq</div><div><br></div><div>youTyped :: String -> String</div><div>youTyped s = s `deepseq` "you typed: " ++ s</div><div><br></div><div>main = do</div><div><span style="white-space:pre-wrap"> </span>hSetBuffering stdin NoBuffering</div><div><span style="white-space:pre-wrap"> </span>s <- getContents</div><div><span style="white-space:pre-wrap"> </span>let l = map youTyped $ lines $ takeWhile ( /= '\04' ) s</div><div><span style="white-space:pre-wrap"> </span>mapM_ putStrLn ("Start Typing (Ctrl-D to exit):":l)</div></div><div style="font-size:13px">--------------------</div><div style="font-size:13px"><br></div><div style="font-size:13px">Output:</div><div style="font-size:13px"><p style="margin:0px;font-size:11px;font-family:Menlo"><br></p><p style="margin:0px;font-size:11px;font-family:Menlo">$ runhaskell deepSeqLazy.hs </p><p style="margin:0px;font-size:11px;font-family:Menlo">Start Typing (Ctrl-D to exit):</p><p style="margin:0px;font-size:11px;font-family:Menlo">Hello world</p><p style="margin:0px;font-size:11px;font-family:Menlo">you typed: Hello world</p><p style="margin:0px;font-size:11px;font-family:Menlo">success</p><p style="margin:0px;font-size:11px;font-family:Menlo">you typed: success</p><p style="margin:0px;font-size:11px;font-family:Menlo">^D</p><p style="margin:0px;font-size:11px;font-family:Menlo"><br></p><p style="margin:0px;font-size:11px;font-family:Menlo">When does it make sense to use seq then?</p></div></div>
<br>_______________________________________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners</a><br>
<br></blockquote></div><br></div>