现在很难看出你想要做什么——但我想你遇到的问题是你会过滤和映射很多。
我认为获得所需内容的简单方法是:
module Combinations where
import Data.List (delete)
combs :: Eq a => Int -> [a] -> [[a]]
combs 0 _ = [[]]
combs i xs = [ y:ys | y <- xs, ys <- combs (i-1) (delete y xs) ]
使用delete
从Data.List
它应该足够懒惰才能快速找到您的组合 - 当然所有这些都需要一段时间;)
λ> take 5 $ combs 5 [1..52]
[[1,2,3,4,5],[1,2,3,4,6],[1,2,3,4,7],[1,2,3,4,8],[1,2,3,4,9]]
它是如何工作的
它是一种递归组合算法,通过y
从所有卡片中选择第一张卡片来工作xs
,然后递归获取s the rest of the hand
ysfrom the deck without the selected card
删除列表单子内的 xs and then putting it back together
y:ys`(此处使用列表理解)。
顺便说一句:有 311,875,200 个这样的套牌;)
没有列表理解的版本
这是一个没有理解的版本,以防您的系统在这里出现问题:
combs :: Eq a => Int -> [a] -> [[a]]
combs 0 _ = [[]]
combs i xs = do
y <- xs
ys <- combs (i-1) (delete y xs)
return $ y:ys
将删除排列的版本
这用于Ord
按升序对项目进行排序,并在此过程中删除与排列相关的重复项 - 预计此工作将xs
被预先排序!
请注意,chi 的版本使用较少的约束,并且可能也更加前瞻 - 但我认为这很好且易读,并且与之前的版本相得益彰,所以您可能会感兴趣。
我知道这不是在 Haskell/FP 中经常做的事情,你为最一般和最抽象的情况而奋斗,但我形成了一个最努力争取可读性和理解力的环境(为程序员编码,不仅为编译器) - 所以要温柔;)
combs' :: Ord a => Int -> [a] -> [[a]]
combs' 0 _ = [[]]
combs' i xs = [ y:ys | y <- xs, ys <- combs' (i-1) (filter (> y) xs) ]