title: Can I use "let" inside "do"?
body: <p>This simple program prints the sum and product of a list of numbers from an input file.</p>
  <pre><code>main :: IO ()
  main = do
    text &lt;- readFile &quot;./input.txt&quot;
    print $ sum [read line | line &lt;- lines text]
    print $ product [read line | line &lt;- lines text]
  
  {-
  
  Example input:
  1
  2
  3
  4
  
  Example output:
  10
  24
  
  -}
  </code></pre>
  <p>It would be nice to avoid repeating <code>[read line | line &lt;- lines text]</code>. If I extract the function <code>printSumAndProduct</code>, I can use a <code>let</code> expression to do this:</p>
  <pre><code>main :: IO ()
  main = do
    text &lt;- readFile &quot;./input.txt&quot;
    printSumAndProduct text
  
  printSumAndProduct :: String -&gt; IO ()
  printSumAndProduct text =
    let numbers = [read line | line &lt;- lines text]
    in do
      print $ sum numbers
      print $ product numbers
  </code></pre>
  <p>However, I would prefer to just have one function, <code>main</code>. <strong>Is it possible to do this without having a separate function <code>printSumAndProduct</code>?</strong></p>
  <p>Here's what I've tried:</p>
  <pre><code>main :: IO ()
  main = do
    text &lt;- readFile &quot;./input.txt&quot;
    let numbers = [read line | line &lt;- lines text]
    in do
      print $ sum numbers
      print $ product numbers
  </code></pre>
  <p>But this is a syntax error:</p>
  <pre><code>main.hs:5:3: error: parse error on input ‘in’
  </code></pre>