groupBy具有多个测试功能

vis*_*vis 4 haskell list

是否有更好,更简洁的方法在Haskell中编写以下代码?我已经尝试过使用if..else但是可读性低于以下内容.我想避免遍历xs列表(这是巨大的!)8次,只是将元素分成8组.groupByfrom Data.List只需要一个测试条件函数:(a -> a -> Bool) -> [a] -> [[a]].

x1 = filter (check condition1) xs
x2 = filter (check condition2) xs
x3 = filter (check condition3) xs
x4 = filter (check condition4) xs
x5 = filter (check condition5) xs
x6 = filter (check condition6) xs
x7 = filter (check condition7) xs
x8 = filter (check condition8) xs
results = [x1,x2,x3,x4,x5,x6,x7,x8]
Run Code Online (Sandbox Code Playgroud)

ehi*_*ird 5

这只遍历列表一次:

import Data.Functor
import Control.Monad

filterN :: [a -> Bool] -> [a] -> [[a]]
filterN ps =
    map catMaybes . transpose .
    map (\x -> map (\p -> x <$ guard (p x)) ps)
Run Code Online (Sandbox Code Playgroud)

对于列表的每个元素,map生成一个Maybes 列表,每个列表Maybe对应一个谓词; 它是Nothing如果元件不满足谓词,或者Just x如果它满足谓词.然后,对transpose所有这些列表进行混洗,以便列表按谓词而不是按元素组织,并map catMaybes丢弃不满足谓词的元素的条目.

一些解释:x <$ mfmap (const x) m,和Maybe,guard bif b then Just () else Nothing,是,x <$ guard b也是if b then Just x else Nothing.

map也可以写成map (\x -> [x <$ guard (p x) | p <- ps]).