多次使用++:如果我从右到左强制进行评估,效率更高?

时间:2011-11-01 15:41:34

标签: haskell

我想在一个表达式中一次附加3个或更多列表。

a ++ b ++ c

将从左到右或从右到左评估++运算符?

1. (a ++ b) ++ c
2. a ++ (b ++ c)

我会说选项2,因为如果++是前缀函数,我们会写++ a ++ b c,这自然会导致首先评估++ b c。我不确定我是否正确。

但如果它是选项1,在我看来,从右到左明确地改变评估顺序更有效:

a ++ (b ++ c)

原因如下:a ++ b ++ c将首先在n个步骤中评估ab ++ c(其中n是a的长度,ab当然是a和b的连接)然后到{{1在n + m个更多的步骤中(m是b的长度,因此n + m是ab的长度),这使得总共2n + m步。鉴于abc将首先以m步为单位评估为a ++ (b ++ c),然后再向n {+ 1}}进行评估,而不仅仅是n + m步。

我是haskell的新手并不确定我在说什么,我想要一些确认。

3 个答案:

答案 0 :(得分:11)

a ++ b ++ c

被解析为

a ++ (b ++ c)

正是您所描述的原因:如果(++)是左关联的,那么a ++ b ++ c会复制a两次。您可以使用

在GHCi中查看
Prelude> :i (++)

将以

回复
infixr 5 ++

其中infixr表示“中缀,右联想”。

答案 1 :(得分:6)

ghci开始,执行:i

Prelude> :i (++)
(++) :: [a] -> [a] -> [a]   -- Defined in GHC.Base
infixr 5 ++

这表明++是(中缀和)右关联,并将从右到左进行评估。我不知道,但是我愿意打赌,当他/她做出正确联想时,实施该问题的人都会考虑到你的问题。

答案 2 :(得分:3)

还有concat函数可以连接任意数量的列表:

Prelude> :t concat
concat :: [[a]] -> [a]
Prelude> concat [[1], [2,3], [42,911]]
[1,2,3,42,911]