title: First three items of a list in Haskell
body: <p>I am very new to Haskell, and struggling a bit with a function here. The premise is simple enough: Run through a list, and combine each 3 items next to each other with another function and return a list with the results. The problem is to do it in a nice way.</p>
  
  <p>Here is what I've got:</p>
  
  <pre class="lang-hs prettyprint-override"><code>foo :: [Int] -&gt; [Int]
  foo xs
      | length xs &lt; 3 = []
      | otherwise     = n : foo (tail xs)
      where n = calc (xs!!0) (xs!!1) (xs!!2)
  
  -- This function is actually significantly more complicated.
  calc :: Int -&gt; Int -&gt; Int -&gt; Int
  calc x y z = x + y - (z * 2)
  
  -- And we can use it like this:
  foo [1,2,3]     -- [-3]
  foo [1,2,3,4]   -- [-3,-3]
  foo [1,1,5,3,3] -- [-8,0,2]
  </code></pre>
  
  <p>What I don't like, is the 5th line, containing all the <code>!!</code>'s. It feels like I'm thinking about it the wrong way, and that there should be a better way of doing this. I'd like to do something like</p>
  
  <pre class="lang-hs prettyprint-override"><code>foo (x:y:z:xs)
      -- ...
  </code></pre>
  
  <p>But that will fail when the list gets less than three items. So, then I'd have to declare other patterns for when the list has fewer items?</p>
  
  <p>Also, in case there is already a function that does what <code>foo</code> does (there probably is, it seems there is one for everything), then I'm not really all that interested in it. I'm trying to grok the Haskell way of doing things, more than expanding my repetoire of functions.</p>
  
  <p><strong>Edit:</strong> In JS, I'd do something like <code>n = calc.apply(null, take(3, xs))</code>. I wonder if Haskell has something like <code>apply</code> that takes an array and applies it to a function as parameters.</p>
  
  <p><strong>Edit 2 -- Solution:</strong> (based on comment below)</p>
  
  <pre><code>foo (x:y:z:xs) = calc x y z : foo (y:z:xs)
  foo _          = []
  </code></pre>
  
  <p>Last pattern match is a catch-all, so if the first "fails" it will fall through and just return an empty list.</p>