Euler 43 - is there a monad to help write this list comprehension?

后端 未结 3 1777
遇见更好的自我
遇见更好的自我 2020-11-29 11:54

Here is a way to solve Euler problem 43 (please let me know if this doesn\'t give the correct answer). Is there a monad or some other syntatic sugar which could assist with

3条回答
  •  清酒与你
    2020-11-29 12:14

    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.

提交回复
热议问题