Haskell算法之间的渐近差异

Haskell asymptotic difference between algorithms

这里我们需要得到给定长度的所有子序列。如何计算给定函数的渐近复杂度?

import Data.List

subsequencesOfSize l n = [x | x <- subsequences l, length x == n]

会有多少"iterations"?我们能谈谈 "iterations" 吗?有什么优化吗? GHC 7.10.2。编译器或程序员如何改进这一点?

我认为您的问题至少包含 2 个不同的问题,但是 GHC(的当前版本)是否可以对此进行优化

subsequencesOfSize l n = [x | x <- subsequences l, length x == n]

变成类似

的东西
subsequencesOfSize l n = [x | x <- subsequences l, lengthIsGt n x, length x == n]

是非常值得怀疑的——我远不是优化、超级编译等方面的专家,但是从这里使用 length 来推断对 lengthIsGt 之类的东西的需求似乎非常重要并且不太可能成为编译器通用优化集的一部分。

P.S。实际上,如果在包含 lengthIsGt 的条件之前对包含 length 的条件进行求值,则带有 lengthIsGt 的版本可能仍会尝试求值无限列表(但这无论如何都是伪代码)

这是一个相关的 SO 问题,它讨论了 subsequencesOfSize 的各种实现:

Haskell: comparison of techniques for generating combinations

以及使用记忆化的表现最好的:

Haskell: comparison of techniques for generating combinations

更新

还要考虑@user3237465 在评论中提到的这个版本:

subsequencesOfSize :: Int -> [a] -> [[a]]
subsequencesOfSize n xs | n > length xs = []
subsequencesOfSize n xs = subsequencesBySize xs !! n where
    subsequencesBySize    []  = [[[]]]
    subsequencesBySize (x:xs) = zipWith (++) ([] : map (map (x:)) next) (next ++ [[]])
        where next = subsequencesBySize xs