expection to this exceptation. On Fri, Dec 9, 2016 at 2:17 PM, Nick H <[email protected]> wrote:
> I would disagree with "not expected in general." In general -- when a and > b are different types -- Elm's API design guidelines should set you up to > always expect a -> b -> b and never b -> a -> b. If the definition of foldl > were changed to take the latter, it would be the only exception to this > expectation. > > On Fri, Dec 9, 2016 at 7:03 AM, Kasey Speakman <[email protected]> > wrote: > >> 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/grou >>>>>>>>>>>> ps/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. >> > > -- 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.
