【发布时间】:2020-06-15 08:38:38
【问题描述】:
考虑以下两个执行顺序:
a ++ (b ++ c)
和
(a ++ b) ++ c
为什么第一个执行顺序比第二个快?
我是 Haskell 新手,希望得到详细的解释,谢谢!
【问题讨论】:
-
你怎么知道它更快?
标签: performance haskell concat lazy-evaluation associativity
考虑以下两个执行顺序:
a ++ (b ++ c)
和
(a ++ b) ++ c
为什么第一个执行顺序比第二个快?
我是 Haskell 新手,希望得到详细的解释,谢谢!
【问题讨论】:
标签: performance haskell concat lazy-evaluation associativity
在充分评估x ++ y的结果时,您必须付费:
x的成本。y 的成本。(++) 操作时遍历一次x 的成本。现在让我们比较a ++ (b ++ c) 和(a ++ b) ++ c。让我们将评估a 的成本写为CA(类似CB、CC),将遍历a 的成本写为TA(类似TB、TC)。那么全面评估a ++ (b ++ c)的成本是:
a, CA 的费用。b ++ c 的费用,即
b 的一次遍历,TB。这是 CA+CB+CC+TA+TB 的总和。现在,对于(a ++ b) ++ c:
a ++ b 的费用,即
a ++ b的一次遍历,即TA+TB。这是 CA+CB+CC+2*TA+TB 的总和。相对于其他订单,多了一个a的遍历,需要额外的TA成本,所以这个订单比较贵。
我留给读者尝试更长的链并开始找出模式。简而言之,坏关联会在每次调用(++) 时重做所有已经完成的遍历,再加上一次,因此会产生二次遍历,而好的关联最多会遍历每个列表一次。
【讨论】:
++ 是infixr 而不是infixl!