Sure.
newtype UniqueSel a = UniqueSel {runUS :: [Int] -> [([Int], a)]}
instance Monad UniqueSel where
return a = UniqueSel (\ choices -> [(choices, a)])
m >>= k = UniqueSel (\ choices ->
concatMap (\ (choices', a) -> runUS (k a) choices')
(runUS m choices))
instance MonadPlus UniqueSel where
mzero = UniqueSel $ \ _ -> []
UniqueSel m `mplus` UniqueSel k = UniqueSel $ \ choices ->
m choices ++ k choices
-- choose something that hasn't been chosen before
choose :: UniqueSel Int
choose = UniqueSel $ \ choices ->
[(pre ++ suc, x) | (pre, x:suc) <- zip (inits choices) (tails choices)]
and then you treat it like the List monad, with guard
to enforce choices, except that it won’t choose an item more than once. Once you have a UniqueSel [Int]
computation, just do map snd (runUS computation [0..9])
to give it [0..9]
as the choices to select from.