簡體   English   中英

單子列表理解方式

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM