Advent of Code #4 in Haskell - Ascending digits with double digit This problem is from Advent of Code day 4 (part 1). The problem is to find the number of ints in the given range satisfying:


all digits are non decreasing
there is at least one group of at least two equal digits in a row


combinations only generates non-decreasing sequences; for example:

λ&gt; combinations 2 ['1'..'3']
["11","12","13","22","23","33"]   


The algorithm generates all non-decreasing combinations from ['0'..'9'], then checks that there's at least one repeating character, that there are no leading zeros, and that the number is in range. Running it with the input 125730-579381 correctly prints 2081.

The main things I want to know about are whether there's a way to improve the algorithm, and whether the readability is good. 

import Data.List (tails, group)
import Control.Arrow
import Control.Monad

-- all non-decreasing combinations of k from xs
combinations :: Int -&gt; [a] -&gt; [[a]]
combinations 0 _ = [[]]
combinations k xs = do
  xs'@(x:_) &lt;- tails xs
  map (x:) $ combinations (pred k) xs'

-- return True iff all predicates are satisfied
allF :: [a -&gt; Bool] -&gt; a -&gt; Bool
allF fs x = and $ map ($ x) fs

-- all ints within the range satisfying:
  -- strictly increasing digits
  -- at least one sequence of exactly 2 of the same digit
solve :: Int -&gt; Int -&gt; Int
solve low hi = length . takeWhile (&lt;= hi) . dropWhile (&lt; low) . map read .
  filter (allF [hasDouble, noLeadingZeros]) $ combinations 6 ['0'..'9']
  where hasDouble = any ((&gt; 1) . length) . group
        noLeadingZeros = (/= '0') . head

main :: IO ()
main = do
  (low, high) &lt;- join (***) read &lt;$&gt; second tail &lt;$&gt; span (/= '-') &lt;$&gt; getLine
  print $ solve low high
Disclaimer: I don't know Haskell and I have never used it before.

solve low hi = length . takeWhile (&lt;= hi) . dropWhile (&lt; low) . map read .
  filter (allF [hasDouble, noLeadingZeros]) $ combinations 6 ['0'..'9']
  where hasDouble = any ((== 2) . length) . group
        noLeadingZeros = (/= '0') . head


Instead of running combinations 6 ['0'..'9'] and then chopping off everything which has a zero at the start, generate numbers from 100000..999999 and then convert it to a string. This would eliminate the combinations method.

I was able to make the following conclusions about the algorithm:


if the numbers are sorted from smallest to largest, then it should equal the original number (i.e. they are already sorted from smallest to greatest)
if the numbers with no duplicates does not equal the original number, then it means that there is at least two which were "de-duped", therefore it has two duplicates


I was able to produce the following code:

import Data.List

checkNum num = do return ((sort(show num) == (show num) &amp;&amp; (nub (show num)) /= (show num)))
main = do checkNum 4222211


This checks if the sorted number (as a string) is equal to itself (which means that it is increasing correctly), and nub removes all duplicate digits.