您的代码几乎可以:
maxL = maximum [length e | e <- entries]
runs = [r | r <- [e | e <- entries, length e == i]] where i = [1..maxL]
除非那样where做。它不是 ; 的同义词foreach。但对于let:
runs = let i = [1..maxL]
in [r | r <- [e | e <- entries, length e == i]]
所以,length e是一个整数,但是i是一个整数[1..maxL]列表。您打算一一i接受这些值,这是通过在列表理解中绑定来完成的:[1..maxL]<-
runs = [ [r | r <- [e | e <- entries, length e == i]] | i <- [1..maxL]]
现在,[r | r <- xs]与 just 相同xs,因此变为
runs = [ [e | e <- entries, length e == i] | i <- [1..maxL]]
使用“标准”功能,这被写成
import Data.List (sortBy)
import Data.Ord (comparing)
runs = group $ sortBy (comparing length) entries
它在算法上也更好。虽然,对于不存在的长度,它不会有空运行,所以两者并不是严格等价的。但这可以通过另一个O(n)结果来解决,
-- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
runs' = snd $ mapAccumL
(\a@ ~((k,g):t) i-> if null a || i<k then (a,[]) else (t,g))
[ (length $ head g, g) | g<- runs]
[ 1..maxL]