Here is a way to solve Euler 43 problem (please let me know if this does not give the correct answer). Is there a monad or some other syntactic sugar that can help track notElem conditions?
toNum xs = foldl (\sd -> s*10+d) 0 xs numTest xs m = (toNum xs) `mod` m == 0 pandigitals = [ [d0,d1,d2,d3,d4,d5,d6,d7,d8,d9] | d7 <- [0..9], d8 <- [0..9], d8 `notElem` [d7], d9 <- [0..9], d9 `notElem` [d8,d7], numTest [d7,d8,d9] 17, d5 <- [0,5], d5 `notElem` [d9,d8,d7], d3 <- [0,2,4,6,8], d3 `notElem` [d5,d9,d8,d7], d6 <- [0..9], d6 `notElem` [d3,d5,d9,d8,d7], numTest [d6,d7,d8] 13, numTest [d5,d6,d7] 11, d4 <- [0..9], d4 `notElem` [d6,d3,d5,d9,d8,d7], numTest [d4,d5,d6] 7, d2 <- [0..9], d2 `notElem` [d4,d6,d3,d5,d9,d8,d7], numTest [d2,d3,d4] 3, d1 <- [0..9], d1 `notElem` [d2,d4,d6,d3,d5,d9,d8,d7], d0 <- [1..9], d0 `notElem` [d1,d2,d4,d6,d3,d5,d9,d8,d7] ] main = do let nums = map toNum pandigitals print $ nums putStrLn "" print $ sum nums
For example, in this case, the appointment of d3 not optimal - it really should be transferred immediately before the numTest [d2,d3,d4] 3 test. However, this would mean modifying some notElem tests to remove d3 from the list being checked. Since consecutive notElem lists notElem obtained by simply passing the last selected value to the previous list, it seems that this should be feasible - somehow.
UPDATE: here is the above program rewritten with Louis UniqueSel monad below:
toNum xs = foldl (\sd -> s*10+d) 0 xs numTest xs m = (toNum xs) `mod` m == 0 pandigitalUS = do d7 <- choose d8 <- choose d9 <- choose guard $ numTest [d7,d8,d9] 17 d6 <- choose guard $ numTest [d6,d7,d8] 13 d5 <- choose guard $ d5 == 0 || d5 == 5 guard $ numTest [d5,d6,d7] 11 d4 <- choose guard $ numTest [d4,d5,d6] 7 d3 <- choose d2 <- choose guard $ numTest [d2,d3,d4] 3 d1 <- choose guard $ numTest [d1,d2,d3] 2 d0 <- choose guard $ d0 /= 0 return [d0,d1,d2,d3,d4,d5,d6,d7,d8,d9] pandigitals = map snd $ runUS pandigitalUS [0..9] main = do print $ pandigitals