Đây là cách tôi muốn viết mã của bạn:
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)
tôi đến mã này như sau. Điều đầu tiên tôi làm là sử dụng mẫu phù hợp thay vì bảo vệ, vì nó rõ ràng hơn ở đây.Điều tiếp theo tôi làm là loại bỏ liftM2
s. Chúng không cần thiết ở đây, bởi vì chúng luôn được gọi với một danh sách kích thước một; trong trường hợp đó, nó giống như gọi map
. Vì vậy, liftM2 (*) ps [10]
chỉ là map (* 10) ps
và tương tự cho các trang web cuộc gọi khác. Nếu bạn muốn có một sự thay thế chung của liftM2
, tuy nhiên, bạn có thể sử dụng Control.Applicative
's <$>
(mà chỉ fmap
là) và <*>
để thay thế cho bất kỳ liftMn
n
: liftMn f a b c ... z
trở thành f <$> a <*> b <*> c <*> ... <*> z
. Có hay không nó đẹp hơn là một vấn đề của hương vị; Tôi tình cờ thích nó. Nhưng ở đây, chúng ta có thể loại bỏ hoàn toàn.
Địa điểm tiếp theo tôi đơn giản hóa mã gốc là do ...
. Bạn không bao giờ thực sự tận dụng thực tế là bạn đang ở trong một -block do
, và do đó, mã có thể trở thành
let ps = increasing (n - 1)
last = map (`mod` 10) ps
next = map (* 10) ps
in alternateEndings next last
Từ đây, đến mã của tôi chủ yếu viết tham gia pha trộn tất cả các map
bạn s với nhau. Một trong những cuộc gọi còn lại duy nhất không phải là map
là zipWith
. Nhưng vì bạn có hiệu quả là zipWith alts next last
, bạn chỉ làm việc với 10*p
và p `mod` 10
cùng một lúc, vì vậy chúng tôi có thể tính toán chúng trong cùng một chức năng. Điều này dẫn đến
let ps = increasing (n - 1)
in concat $ map alts ps
where alts p = map (10*p +) [y `mod` 10..9]
Và điều này về cơ bản là mã của tôi: concat $ map ...
nên luôn luôn trở thành concatMap
(trong đó, tình cờ, là =<<
trong danh sách đơn nguyên), chúng tôi chỉ sử dụng ps
một lần vì vậy chúng tôi có thể gấp nó vào, và tôi thích let
đến where
.
1: Về mặt kỹ thuật, điều này chỉ làm việc cho Applicative
s, vì vậy nếu bạn tình cờ được sử dụng một đơn nguyên đã không được thực hiện một, <$>
là `liftM`
và <*>
là `ap`
. Tất cả các monads có thể được thực hiện functors applicative, mặc dù, và nhiều người trong số họ đã được.
Tôi đã chọn câu trả lời này là câu trả lời được chấp nhận vì câu trả lời gần giống nhất với câu hỏi gốc. Tuy nhiên, như các câu trả lời khác chỉ ra dưới đây, tôi đã thực sự đặt câu hỏi sai, và giải pháp có thể được biểu diễn đơn giản hơn. – stusmith