[英]Monadic way for list comprehension
我有以下功能
combinations :: [[a]] -> [[a]]
combinations [] = [[]]
combinations (xs:xss) = concat [map (x:) yss | x <- xs]
where yss = combinations xss
產生其元素之間的所有組合:
*Main> combinations [[1,2],[2,3,4],[5,6]]
[[1,2,5],[1,2,6],[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,2,5],[2,2,6],[2,3,5],[2,3,6]
,[2,4,5],[2,4,6]]
我覺得一定有一種單調的方式來做到這一點
foobar = do
n <- [1,2]
ch <- [3,4,5]
return[n,ch]
這就是我走了多遠。 但是我被困住了。
您的功能是列表單子的sequence
。
> :t sequence
sequence :: Monad m => [m a] -> m [a]
> sequence [[1,2],[2,3,4],[5,6]]
[[1,2,5],[1,2,6],[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,2,5],[2,2,6],[2,3,5],[2,3,6],
[2,4,5],[2,4,6]]
我能想到的最好的是
combinations [] = [[]]
combinations (xs:xss) = do
x <- xs
ys <- combinations xss
return $ x : ys
我的推導方法是,我首先將列表理解轉換為單子代碼(這也意味着刪除concat
使其進行類型檢查)。
combinations (xs:xss) =
let yss = combinations xss
in do
x <- xs
map (x:) yss
然后我意識到map (x:) yss
恰好是fmap (x:) yss
,也就是yss >>= return . (x:)
yss >>= return . (x:)
,所以我知道我可以做
combinations (xs:xss) =
let yss = combinations xss
in do
x <- xs
ys <- yss
return $ x : ys
然后可以內聯為
combinations (xs:xss) = do
x <- xs
ys <- combinations xss
return $ x : ys
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.