Reusing ++: more efficiently if I force right-to-left value?

I want to add 3 or more lists at once in one expression.

a ++ b ++ c 

Will the ++ operator be evaluated from left to right or from right to left?

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

I would say option 2, because if ++ was a prefix function, we write ++ a ++ bc , which naturally leads to the evaluation of ++ bc in the first place. I am not sure that I am right.

But if this is option 1, it seems to me that a more effective change in the evaluation order from right to left is more efficient:

 a ++ (b ++ c) 

Here's why: a ++ b ++ c will first evaluate to ab ++ c by n steps (where n is the length of a, and ab is, of course, the concatenation of a and b), and then to abc at n + m more steps (m is the length of b, so n + m is the length of ab), which is only 2n + m steps. While a ++ (b ++ c) will be evaluated first to a ++ bc in m steps, and then to abc for more than n steps, which is the sum of only n + m steps.

I am new to haskell and not sure what I'm saying, I would like to receive confirmation.

+6
source share
3 answers
 a ++ b ++ c 

analyzed as

 a ++ (b ++ c) 

exactly for the reasons you describe: if (++) was left-associative, then a ++ b ++ c double-copied a . You can check it in GHCi with

 Prelude> :i (++) 

who will answer

 infixr 5 ++ 

where infixr means "infix, right-associative."

+11
source

From ghci , do a :i :

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

Which shows that ++ is (infix and) right-associative and will be evaluated from right to left. I don’t know, but I would bet that the one who implemented this had your question when he made it correctly associative.

+6
source

There is also a concat function that combines any number of lists:

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

Source: https://habr.com/ru/post/900530/


All Articles