Haskell 高阶函数的计算复杂性?

Haskell 高阶函数的计算复杂性?,haskell,functional-programming,complexity-theory,higher-order-functions,Haskell,Functional Programming,Complexity Theory,Higher Order Functions,Map和filter看起来是线性的O(n),因为它们只需要遍历一次列表,但是它们的复杂性是否受到传递的函数的影响?例如,以下两个示例的顺序是否相同 map (+) list map (complex_function) list 您似乎(普遍)误解复杂性是n的函数 什么是n n只是一个衡量输入的参数。它可能不是描述输入的充分(甚至是必要的)统计数据——您可能需要其他变量来准确描述输入的复杂性 因此,map和filter在n中是线性的。它们对其他变量的依赖性取决于您传递的函数,但它们对n的依赖

Map和filter看起来是线性的O(n),因为它们只需要遍历一次列表,但是它们的复杂性是否受到传递的函数的影响?例如,以下两个示例的顺序是否相同

map (+) list

map (complex_function) list
您似乎(普遍)误解复杂性是
n
的函数

什么是
n

n
只是一个衡量输入的参数。它可能不是描述输入的充分(甚至是必要的)统计数据——您可能需要其他变量来准确描述输入的复杂性

因此,
map
filter
n
中是线性的。它们对其他变量的依赖性取决于您传递的函数,但它们对
n
的依赖性通常不是


(脚注:是的,你可以将一个函数传递给
map
filter
,当它处理更多的元素时,它实际上执行更多的工作,但这并不有趣,也与我在这里试图说明的问题无关。)

在几乎所有情况下,当一个高阶函数的文档说明它的复杂性是
O(f(n))
,这是假设高阶函数具有恒定的时间复杂度
O(1)
。此外,
n
的确切含义可能会有所不同,但如果没有明确说明,则应该从上下文中明确:例如列表的长度、集合/映射中元素/关联的数量等等

假设我们有一个高阶函数
g
称为
gh…
,其中
h
是一个函数,
..
是一阶数据。在没有关于高阶函数
g
的任何其他信息的情况下,如果文档中说明它是
O(f(n))
,则可以得到更实际的最坏情况界
O(f(n))*CostH
,其中
CostH
表示调用
H
一次的成本

当然,
CostH
也将取决于哪些参数开始传递给
h
:在这里,我们所知道的是这些参数是在
O(f(n))
时间内构建的。很难得到
h
参数大小的有用的一般界限,因为,例如,如果
h
将树作为输入,那么您可以在短时间内构建一个非常大的树:

foo :: Int -> Tree ()
foo 0 = Tree []
foo m = Tree [t,t] where t = foo (m-1)
上面构建了一棵树,树的
2^m
叶在
m
时间内(由于共享)。这可以适应
3^m
b^m
简单地保持
b*m
复杂性

然而,可能有一些方法可以利用参数来恢复更有用的边界。例如,如果我们的order函数具有类型

g :: (a -> Int) -> [a] -> Int
然后我们知道
gh[…]
只能使用列表中的参数调用
h
。类似地,库函数调用
sortBy h[…]
只能使用
h
来比较所提供列表中的两个元素


然而,我不知道如何形式化和证明上述概述。很可能有一些关于这一主题的研究论文。

有关复杂性和高阶函数的背景知识,请参阅,例如

霍夫曼,马丁。范畴论语义学在使用高阶函数代数描述复杂类中的应用


公牛。符号逻辑3(1997),第4469-486号

一个很好的例子可能是
filter isPrime[1..n]
最好总结一些要点(特别是关于这个问题),因为这是一个非现场链接(这里不鼓励只提供链接的答案)而且它还需要订阅才能查看。我从来没有想过使用Parametercity从稀薄的空气中提取时间限制。我认为它的实用性相当有限,尽管你提供的任何信息都可以提供给忙碌的海狸或其他类似的人。你确定这个脚注吗?我不明白你怎么能做这样的事情,尽管
travel
filterM
当然可以。我错过什么了吗?@dfeuer:我想是吧?只需将看到的每个元素附加到数组中,并在执行此操作之前对整个数组执行额外的虚拟扫描。如果使用
unsafePerformIO