Lucky Triples in Haskell
If mapFactors' is put in a where clause of mapFactors, it isn't globally accessible and you can call it go or something because the scoping already points out it belongs to mapFactors.

Swapping gos argument order lets you say mapFactors = go [].

++ [_] is a smell. Instead of passing down an accumulator and growing it to the right, you can pass it out as the return value and grow it to the left.

mapFactors :: [Int] -&gt; [[Int]]
mapFactors = go where
  go [] = []
  go (x:xs) = newAcc $ go xs where
    factors = filter ((==0) . (`mod` x)) xs
    newAcc | null factors = id
           | otherwise = (:) factors


The filtering can happen after go is done.

mapFactors :: [Int] -&gt; [[Int]]
mapFactors = filter (not . null) . go where
  go [] = []
  go (x:xs) = filter ((==0) . (`mod` x)) xs : go xs


tails helps express go in terms of map:

mapFactors :: [Int] -&gt; [[Int]]
mapFactors = filter (not . null) . map go . tails where
  go [] = []
  go (x:xs) = filter ((==0) . (`mod` x)) xs


Let's use sum from that comment and inline the once-used twoStepFactors (imo if you're only giving a name to explain what something does, use comments)

answer :: [Int] -&gt; Int
answer xs = sum $ map (sum . map length . mapFactors) $ mapFactors $ sort xs


There doesn't seem to be a reason to filter out the []s.

List comprehensions neatly let us skip the empty tail, and get rid of go.

mapFactors :: [Int] -&gt; [[Int]]
mapFactors xss = [filter ((==0) . (`mod` x)) xs | x:xs &lt;- tails xss]