(deleted and corrected original post with proper expansion of Elm's foldl)

I know this is a really old thread, but I ran into this precise question 
and thought I would add a perspective.

The form a -> b -> b is not left-building, regardless of the direction you 
are traversing the list.

An example: Starting from zero, subtract the numbers 1, 2, and 3. The 
expected answer is -6.

List.foldl (-) 0 [1, 2, 3]
-> returns -6 in Haskell (well, actually tested in F# which uses same order 
as Haskell)
    expands to: ((0 - 1) - 2) - 3 = -6
-> returns 2 in Elm
    expands to: 3 - ((1 - 0) - 2)

Elm's expansion is wonky for this. It appears to be center-building:
    List.foldl (-) 0 [1] -- returns 1, expands 1 - 0
    List.foldl (-) 0 [1, 2] -- returns -1, expands (1 - 0) - 2
    List.foldl (-) 0 [1, 2, 3] -- returns 2, expands 3 - ((1 - 0) - 2)
    List.foldl (-) 0 [1, 2, 3, 4] -- returns -2, expands (3 - ((1 - 0) - 
2)) - 4

When a and b are the same type it will only return the correct answer if 
the fold operation is also commutative or if flip is used to correct the 
ordering. When a and b are not the same type, the compiler will provide an 
error for wrong ordering of course.

I started out on the side that a -> b -> b was correct as that feels like 
proper "reduction" or chainable syntax. But after exploring it, it is 
clearly not left-building. Makes sense when you consider this form is used 
with pipe to convert right-building operations into left-reading code. e.g. a 
|> f |> g |> h instead of h (g (f a))

On Tuesday, July 16, 2013 at 6:13:01 AM UTC-5, Evan wrote:
>
> Gotcha, I definitely see the reasoning :)
>
>
> On Tue, Jul 16, 2013 at 12:54 PM, Balazs Komuves <[email protected] 
> <javascript:>> wrote:
>
>>
>> I was not engaging in debate, religious or not (though I tend to have 
>> very strong opinions about these questions). I was explaining why I think 
>> Haskell uses the order it uses (because it is distinguished from a 
>> mathematical viewpoint). Of course you are not required to follow that 
>> convention, I was just pointing out that it is not simply an ad-hoc choice.
>>
>> Balazs
>>
>>
>>
>> On Tue, Jul 16, 2013 at 12:21 PM, Evan Czaplicki <[email protected] 
>> <javascript:>> wrote:
>>
>>> I think this might be a religious debate on some level. My first 
>>> functional languages were Scheme 
>>> <http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/list..rkt)._foldl))>
>>>  
>>> and Standard ML <http://www.standardml.org/Basis/list.html>. The 
>>> libraries I just linked both use the same argument order for foldl and 
>>> foldr as in Elm. I was raised a certain way and it just stuck in my mind. I 
>>> suspect that everyone prefers the order they learned first because it 
>>> matches their mental model.
>>>
>>> I wrote up a bunch of "reasoning", but really, I am just engaging in the 
>>> religious debate. I'd feel bad deleting it all though, so here is some of 
>>> it:
>>>
>>> OCaml's list library 
>>> <http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html> does it 
>>> the way you suggest. I find this order offensive on some level.
>>>
>>> The big questions for "physical" argument order are as follows:
>>>
>>>    - What is the type of `fold` or `reduce`? When you fold an unordered 
>>>    thing, is it from the right or the left? 
>>>    - What is the type of `foldp`? Which way does time go? Is this 
>>>    cultural?
>>>
>>> I don't find these questions particularly useful, and I don't think 
>>> programmers should have to wonder about them to use fold and foldp.
>>>
>>> At the end of the day, I chose the types on purpose. I find them easier 
>>> to use, easier to teach, easier to understand. I want to keep them this way.
>>>
>>>
>>> On Tue, Jul 16, 2013 at 10:40 AM, Balazs Komuves <[email protected] 
>>> <javascript:>> wrote:
>>>
>>>>
>>>> The Haskell version of the foldl is the "right one" in the following 
>>>> sense:
>>>>
>>>> foldl makes sense in general for left-associative operators, and foldr 
>>>> makes sense for right-associative operators.
>>>> Left-associative operators must have the type (a -> b -> a), while 
>>>> right-associative operators must have type (a -> b -> b).
>>>>
>>>> I think the fact that you cannot change a foldr to foldl without 
>>>> changing the types is actually an advantage: it forces you to think about 
>>>> which version is the "proper" one, and you cannot accidentally do the 
>>>> wrong 
>>>> one. Of course sometimes it can be inconvenient.
>>>>
>>>> What I somewhat dislike in the Haskell version of foldr (not foldl), is 
>>>> that while 
>>>>
>>>> (foldl . foldl . foldl) etc makes sense, (foldr . foldr) does not; for 
>>>> that to work you would have to flip the last two arguments:
>>>>
>>>> myfoldr :: (a -> b -> b) -> ([a] -> b -> b)
>>>> myfoldr f xs y = foldr f y xs
>>>>
>>>> But the practicality of this change is debatable, I guess.
>>>>
>>>> Balazs
>>>>
>>>>
>>>>
>>>>
>>>> On Wed, Jul 10, 2013 at 4:38 PM, Evan Czaplicki <[email protected] 
>>>> <javascript:>> wrote:
>>>>
>>>>> It's partly about composability (i.e. the data structure should be 
>>>>> last).
>>>>>
>>>>> It is also about reuse. In Elm it is valid to say:
>>>>>
>>>>> foldl (::) []
>>>>> foldr (::) []
>>>>>
>>>>> If I want to change the order of my traversal, I should not *also* need 
>>>>> to change the definition of mildly related functions or start using 
>>>>> flip on things.
>>>>>
>>>>> Finally, once you know that the accumulator is always the second 
>>>>> argument, you do not have to look at docs anymore. Even now I forget the 
>>>>> order of arguments in Haskell's folds and need to look it up.
>>>>>
>>>>> I first learned this way from Standard ML 
>>>>> <http://www.standardml.org/Basis/list.html>, and it is my favorite by 
>>>>> far.
>>>>>
>>>>>
>>>>> On Wed, Jul 10, 2013 at 4:12 PM, Tim hobbs <[email protected] 
>>>>> <javascript:>> wrote:
>>>>>
>>>>>> Well, elm's ordering is more useful.  For example, I recently had a 
>>>>>> case where I wrote:
>>>>>>
>>>>>> let
>>>>>>   irrelivantFuncitonName fold = fold blabla default list
>>>>>> in
>>>>>>  irrelivantFunctionName foldl + irrelivantFuncitonName foldr
>>>>>>
>>>>>> In Haskell, the same example ends up being
>>>>>>
>>>>>> let
>>>>>>   irrelivantFuncitonName fold = fold blabla default list
>>>>>> in
>>>>>>  irrelivantFunctionName foldl + irrelivantFuncitonName (\f d l-> 
>>>>>> foldr (\a b->f b a) d l)
>>>>>>
>>>>>> Tim
>>>>>>
>>>>>>
>>>>>> On Wednesday, July 10, 2013 4:03:23 PM UTC+2, Zsombor Nagy wrote:
>>>>>>>
>>>>>>> Hi! 
>>>>>>>
>>>>>>> I wonder why is the foldl in Elm and in Haskell calling the binary 
>>>>>>> operator with arguments in a different order? 
>>>>>>>
>>>>>>> foldl (\t acc -> acc + 1) 0 [1, 1, 1, 1, 1, 1] 
>>>>>>> haskell: 2 
>>>>>>> Elm: 6 
>>>>>>>
>>>>>>> For me the haskell way seems more straightforward, but maybe that 
>>>>>>> "optimal composibility guideline" makes this turn around? 
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> zs
>>>>>>
>>>>>> -- 
>>>>>> You received this message because you are subscribed to the Google 
>>>>>> Groups "Elm Discuss" group.
>>>>>> To unsubscribe from this group and stop receiving emails from it, 
>>>>>> send an email to [email protected] <javascript:>.
>>>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>>>  
>>>>>>  
>>>>>>
>>>>>
>>>>> -- 
>>>>> You received this message because you are subscribed to the Google 
>>>>> Groups "Elm Discuss" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>>> an email to [email protected] <javascript:>.
>>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>>  
>>>>>  
>>>>>
>>>>
>>>> -- 
>>>> You received this message because you are subscribed to the Google 
>>>> Groups "Elm Discuss" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to [email protected] <javascript:>.
>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>  
>>>>  
>>>>
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Elm Discuss" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to [email protected] <javascript:>.
>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>  
>>>  
>>>
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Elm Discuss" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to [email protected] <javascript:>.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>  
>>  
>>
>
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to