Ways of forming multiple elements in a list comprehension without duplicates (Euler #109)
Your threeshots line

Since using the operator !! is not very Haskelly, let's get rid of that and think of a way to get your b and c using typical list operations. Since you want a list of all pairs, let's create a new function called pairs.

pairs :: [a] -&gt; [(a,a)]
pairs [] = []
pairs (x:xs) = map (\y -&gt; (x, y)) (x:xs) ++ pairs xs


Your new threeshots would thus be:

threeshots = [a + b + c | a &lt;- doubles, (b, c) &lt;- pairs alls]


In a nutshell, pairs takes the first element of the given list, forms tuples with every element of that list and continues with the rest of the list until it's empty.

If you prefer, you could write pairs (x:xs) as map ((,) x) (x:xs) ++ pairs xs. I find that one to be less clear, though.

Other Nitpicks

As a rule of thumb, every top level declaration should have a type annotation.

You've declared your main in a do-block, which is not necessary since you're not using any monadic stuff. The (++oneshots) $ (++twoshots) threeshots part looks unusual, too.

main = print . length . filter (&lt; 100) $ threeshots ++ twoshots ++ oneshots


You can keep the $ in your main if you prefer; in this scenario, it's probably just a matter of taste. Using . is less noise though - to me at least.

Putting it all together

singles, doubles, triples, alls :: [Int]
singles = [1..20] ++ [25]
doubles = map (*2) singles 
triples = map (*3) [1..20]
alls    = singles ++ doubles ++ triples

pairs :: [a] -&gt; [(a, a)]
pairs []     = []
pairs (x:xs) = map (\y -&gt; (x, y)) (x:xs) ++ pairs xs

oneshots, twoshots, threeshots :: [Int]
oneshots   = doubles
twoshots   = [a + b | a &lt;- doubles, b &lt;- alls]
threeshots = [a + b + c | a &lt;- doubles, (b, c) &lt;- pairs alls]

main :: IO ()
main = print . length . filter (&lt; 100) $ threeshots ++ twoshots ++ oneshots