Вот как бы я написал ваш код:
increasing :: Integer -> [Integer]
increasing 1 = [1..9]
increasing n = let allEndings x = map (10*x +) [x `mod` 10 .. 9]
in concatMap allEndings $ increasing (n - 1)
Я пришел к этому коду следующим образом.Первым делом я использовал сопоставление с образцом вместо охранников, так как здесь все понятно.Следующим, что я сделал, было устранение liftM2
s.Они здесь не нужны, потому что они всегда вызываются с одним списком размера один;в этом случае это все равно что звонить map
.Так что liftM2 (*) ps [10]
это просто map (* 10) ps
, и аналогично для других сайтов вызовов.Если вы хотите обычную замену liftM2
, вы можете использовать Control.Applicative
<$>
(то есть просто fmap
) и <*>
для замены liftMn
для любого n
: liftMn f a b c ... z
становится f <$> a <*> b <*> c <*> ... <*> z
.Хорошее это или нет - дело вкуса;Мне это нравится. 1 Но здесь мы можем полностью это исключить.
Следующее место, где я упростил исходный код, это do ...
.На самом деле вы никогда не воспользуетесь тем фактом, что находитесь в do
-блоке, и поэтому код может стать
let ps = increasing (n - 1)
last = map (`mod` 10) ps
next = map (* 10) ps
in alternateEndings next last
Отсюда, получение моего кода по сути связано с написанием слияния всех ваших map
с вместе.Один из оставшихся вызовов, который не был map
, был zipWith
.Но поскольку у вас фактически есть zipWith alts next last
, вы работаете только с 10*p
и p `mod` 10
одновременно, поэтому мы можем вычислить их в одной и той же функции.Это приводит к
let ps = increasing (n - 1)
in concat $ map alts ps
where alts p = map (10*p +) [y `mod` 10..9]
И это в основном мой код: concat $ map ...
всегда должен становиться concatMap
(что, кстати, =<<
в монаде списка), мы используем ps
только один разтак что мы можем сложить его, и я предпочитаю от let
до where
.
1: Технически, это работает только на Applicative
с, так что если вы случитесьчтобы использовать монаду, которая не была сделана, <$>
- это `liftM`
, а <*>
- `ap`
.Все монады могут быть сделаны аппликативными функторами, и многие из них были.