File manipulation with Haskell
contents &lt;- fmap tail . fmap lines . readFile $ "testInput"


can be written as

contents &lt;- (tail . lines) &lt;$&gt; readFile "testInput"


Here we take advantage of the law fmap f . fmap g == fmap (f . g). &lt;$&gt; is an infix version of fmap. $ is extraneous here.



let input = map pair_to_tuple .(map (map read)) . map words $ contents :: [(Int,Int)]


can be written as

let input = map (pair_to_tuple . (map read) . words) contents :: [(Int,Int)]


For lists map = fmap, so map f . map g == map (f . g) also holds.



In

let result = map (uncurry waffles) $ input


the $ sign is also extraneous.



let decorated_result = ["Case #" ++ show i ++ ": " ++ show s | (i,s) &lt;- zip [1..length result] result]


You can exploit Haskell's lazy evaluation and create infinite list to zip with:

let decorated_result = ["Case #" ++ show i ++ ": " ++ show s | (i,s) &lt;- zip [1..] result]




Otherwise I'd say the code is fine.