Ok, correction

List.foldl (-) 0 [1, 2, 3]
-- returns 2
-- expands to 3 - (2 - (1 - 0)) = 2

During my testing last night, I had a typo (foldr instead of foldl) when I 
was testing the expansions. That was the center-building behavior.

Using the form a -> b -> b is right-building regardless of the order the 
list is traversed. Traversing from head to tail is equivalent to reversing 
the list and building right. This is obviously broken for left-associative 
only operations and not expected in general.

On Friday, December 9, 2016 at 8:44:25 AM UTC-6, Kasey Speakman wrote:
>
> Sorry, that last bit was an example of what happens in Elm when folding 
> with string concat (++). That's unexpected behavior from a left fold.
>
> List.foldl (++) "" ["The ", "quick ", "brown "]  -- returns "brown quick 
> The "
>
> On Friday, December 9, 2016 at 8:26:17 AM UTC-6, Kasey Speakman wrote:
>>
>> You're confusing pipe's syntax and infix. Pipe is defined like this:
>>
>> (|>) x f = f x
>>
>> And used like this
>>
>> x |> f == f x
>>
>> So pipe has an inherent flip because it is used to chain otherwise 
>> right-building statements.
>>
>> e.g. 
>>
>> List.sum (List.filter isOdd [1, 2, 3])
>>
>> vs
>>
>> [1, 2, 3]
>> |> List.filter isOdd
>> |> List.sum
>>
>> Pipe is inherently right-building, so operations like subtract or string 
>> concatenation are not suitable for it since they are only left associative.
>>
>> List.foldl (++) "" ["The ", "quick ", "brown "]  -- returns "brown quick 
>> The "
>>
>> On Friday, December 9, 2016 at 1:05:56 AM UTC-6, Aaron VonderHaar wrote:
>>>
>>> What's confusing here is how currying works with infix operators.  It's 
>>> idiomatic in Elm to have your accumulator be the last argument, and, for 
>>> instance, if you were writing your own data type, you would want to write 
>>> your functions so that they can be chained together easily:
>>>
>>>     myMatrix
>>>         |> scale 2
>>>         |> subtract 5
>>>         |> subtractMatrix myOtherMatrix
>>>         |> normalize
>>>
>>>
>>> But as an infix operator (-) is not able to follow that convention;
>>>
>>>     5
>>>         |> (-) 3
>>>         |> (-) 1
>>>
>>> is confusingly equivalent to `(1 - (3 - 5))` rather than to `5 - 3 - 1`
>>>
>>>
>>> If you had a function `subtract` such that
>>>
>>>     5 |> subtract 3 |> subtract 1 == (5 - 3 - 1)
>>>
>>> then you could use that function with fold as you intend
>>>
>>>     List.foldl subtract 0 [1, 2, 3, 4]  ==  -10
>>>
>>> You can achieve the same result with
>>>
>>>     List.foldl (flip (-)) 0 [1, 2, 3, 4]  ==  -10
>>>
>>>
>>> Another way to put it is, in Elm, folds expand in the following way:
>>>
>>>     List.foldl f x [b, c, d]  ==  x |> f b |> f c |> f d 
>>>     List.foldr f x [b, c, d]  ==  f b <| f c <| f d <| x
>>>
>>>
>>> On Thu, Dec 8, 2016 at 7:50 PM, Kasey Speakman <[email protected]> 
>>> wrote:
>>>
>>>> (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]> 
>>>>> 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]> 
>>>>>> 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]> 
>>>>>>> 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]> 
>>>>>>>> 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]> 
>>>>>>>>> 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].
>>>>>>>>>> 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/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/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/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/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.
>>>>
>>>
>>>

-- 
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