title: Understanding the different behavior of thunks when GHCi let bindings are involved
body: <p>I've been playing with some examples from Simon Marlow's book about parallel and concurrent
  programming in Haskell and stumbled across an interesting behavior that I don't really understand. This is really about me trying to understand some of the inner workings of GHC.</p>
  
  <p>Let's say I do the following in the REPL:</p>
  
  <pre><code>λ» let x = 1 + 2 :: Int
  λ» let z = (x,x)
  λ» :sprint x
  x = _
  λ» :sprint z
  z = (_,_)
  λ» seq x ()
  ()
  λ» :sprint z
  z = (3,3)
  </code></pre>
  
  <p>Ok, this is pretty much what I expected except that z gets evaluated to WHNF already. Let's write a similar program and put it in a file:</p>
  
  <pre><code>module Thunk where
  
  import Debug.Trace
  
  x :: Int
  x = trace "add" $ 1 + 2
  
  z :: (Int,Int)
  z = (x,x)
  </code></pre>
  
  <p>And fiddle around with it in GHCi:</p>
  
  <pre><code>λ» :sprint x
  x = _
  λ» :sprint z
  z = _
  λ» seq x ()
  add
  ()
  λ» :sprint z
  z = _
  λ» seq z ()
  ()
  λ» z
  (3,3)
  </code></pre>
  
  <p>So this behaves a little different: <code>z</code> is not evaluated to WHNF in advance. My question is:</p>
  
  <p>Why is <code>z</code> evaluated to WHNF in the REPL when doing <code>let z = (x,x)</code> but not when loading the definition from a file. My suspicion is that
  it has something to do with pattern binding but I don't know where to look that up for clarification (maybe I'm just completely utterly wrong). I would have expected it to somehow behave like the example in the file.</p>
  
  <p>Any pointers or a brief explanation why this happens?</p>