Haskell for Imperative Programmers #9 - Folding (foldr, foldl)

Поділитися
Вставка
  • Опубліковано 12 січ 2025

КОМЕНТАРІ • 55

  • @lucaricchi5873
    @lucaricchi5873 4 роки тому +47

    the map implementation with foldr was mindblowing ;)

    • @emilianomarshall5257
      @emilianomarshall5257 3 роки тому

      I guess it is kinda randomly asking but does anybody know a good website to stream new movies online?

  • @MithicSpirit
    @MithicSpirit 2 роки тому +12

    10:39 the order in which data is processed and the order of operations are two different things, and, due to non-commutative functions, the order *can* matter. For example, consider `foldDiv = foldr (/) 1.0`; the order of the elements does matter in this case (`foldDiv [1, 2, 3]` returns 1.5, while `foldDiv [1, 3, 2]` returns approximately ⅔)

  • @elultimopujilense
    @elultimopujilense 3 роки тому +11

    OMG never ever imagined that I could build anything from scratch so elegantly using functional programming! this is unreal, is just mind blowing how everything just makes sense!

    • @sentzeu
      @sentzeu Рік тому +1

      Once you escape the Matrix of Object-Oriented Programming and understand the elegant Platonic Ideal Realm of Functional Programming Paradigms it changes how you think about coding. None of the projects I write use Haskell, but learning it changed how I write Java code.

    • @elultimopujilense
      @elultimopujilense Рік тому

      @@sentzeu I totally agree. OOP has many real world applications and teaches you to think in terms of objects, but without the elegance of functional programming, you just cant get the most out of OOP. Functional programming makes you think and program in terms of math, the language of the universe. It just takes programming to a different new awesome level.

  • @vadrrigar5084
    @vadrrigar5084 3 роки тому +2

    Very good explanation. The explanation from chapter 7 in "Programming Haskell" did not really click for me, but your video made finally clear to me. Thanks!

  • @inigo8740
    @inigo8740 4 роки тому +15

    If the function used in folding isn't commutative then the order in which you traverse a tree matters.

  • @santypk5
    @santypk5 3 роки тому +2

    This is awesome!!!
    Folding L is the same as Reduce in JavaScript

  • @micknamens8659
    @micknamens8659 3 роки тому +1

    5:00 There is another way to define "isAll" using a point-free function within foldl':
    isAll1 e = foldl' ( (&&) .^ (==e) ) True
    where (f .^ g) x y = f x (g y) -- or imported from pointless-fun Data.Function.Pointless.
    For foldr there is no matching predefined function, but we could adjust ".^" with flip:
    isAll2 e = foldr ( flip $ (&&) .^ (==e) ) True

  • @kantamana1
    @kantamana1 2 місяці тому

    Here is something mind-blowing for you. Foldr is not tail recursive, and we therefore want to use foldl instead to prevent stack overflow, which is tail recursive. Here is what people tend to think: "as long as the fold function is commutative, i can use foldl and foldr interchangeably, and if not i can just swap the arguments". The reality is that you also need the fold function to be *associative*, and if it isn't, there is generally no way to make a foldr into a foldl, and no way to make it tail-recursive, even if you implement it yourself.

  • @Daniel-ws9qu
    @Daniel-ws9qu 5 років тому +9

    if the operator (op) is not comutative,
    is foldr (op) z [a,b,c,d] then equivalent to
    a op (b op (c op (d op z)))
    ? (so that the most right operation binds the strongest)

    • @Daniel-ws9qu
      @Daniel-ws9qu 5 років тому +1

      Yes it does, didn't whatch to the end

    • @kantamana1
      @kantamana1 2 місяці тому

      it has to be associative too

  • @jantonisito
    @jantonisito 2 роки тому

    AT 1:38 in your example xn is of type a and a is of type b - correct? It makes a bit hard at first the reconcile it with (a -> b -> b) -> b -> [a] -> b on top of th screen. I understand that the first a is tha name of type and the other is name of parameter but first time you read it you get turned around

  • @breesantos2885
    @breesantos2885 3 роки тому +3

    Vielen Dank für die Haskell-Tutorials! ich studiere grad Informatik in den USA und es gibt kaum genug YT Content über Haskell im Vergleich zu Python, Java usw

  • @simon-myunggun-seo
    @simon-myunggun-seo 4 роки тому +7

    Is folding the same as “reduce” used in some programming languages/frameworks?

    • @SamWhitlock
      @SamWhitlock 4 роки тому +4

      Yes very much so. You can think of fold (at a high level) as "reduce (\x acc -> ...) . map (\y -> ...)", but the functions can be rolled into one (e.g. transforming while reducing in the same function.

    • @0LoneTech
      @0LoneTech 2 роки тому +1

      More generally, a reduce may operate in arbitrary order, suitable for a semigroup (i.e. associative functions, as was assumed at the end of this video). Left/right folds specify the ordering. In practice reduce is often implemented as a left fold, but using it with a monoid allows starting in more than one place for parallel evaluation. This may make more sense for chunked or tree structures than lists.
      The 1 variants of fold start at some element within the foldable, which is also often how reduce operates. That way the zero value of the monoid isn't needed.

  • @Bbdu75yg
    @Bbdu75yg 2 роки тому

    4:52 why is the $ sign necessary? Couldn’t we just write in the end
    Foldr( ….. -> (&&) e==x)
    ??

    • @noya3004
      @noya3004 11 місяців тому

      I was wondering this as well, I really don't get it. Still no answers

    • @0LoneTech
      @0LoneTech 10 місяців тому

      $ is never necessary; it only manipulates precedence. It could be replaced with the appropriate parenthesis, so (&&) (e==x).
      Function application has very high precedence, so just removing $ produces ((&&) e)==x, which requires e to be Bool and x to be equality comparable to a partially applied &&, but functions are not comparable so that won't work.
      Another way to write (\x -> (&&) $ e==x) is ((&&) . (e==)). And despite what was said in this session, you should not fear "iterating twice" because Haskell can fuse loops like "and . map ((==) e)" (better spelled "all (e==)").

  • @ZwanzigEldeai
    @ZwanzigEldeai 4 роки тому +2

    Thank you, this was very helpful.

  • @grego1388
    @grego1388 9 місяців тому

    muy bien explicado, sos crack philipp ee

  • @gregbell2117
    @gregbell2117 4 роки тому +1

    Is it correct that the 2 is visited twice in the pre- and post- tree fold orders? Wouldn't that make count, map, etc. impossible?

    • @philipphagenlocher
      @philipphagenlocher  4 роки тому +1

      That was just a bad way of visualizing on my part. The "2" node will always be visited only a single time. The arrows are meant to signify the "flow" of the folding, if that makes sense. ;)

    • @ronaldc8634
      @ronaldc8634 3 роки тому

      I had the same question

  • @NicholasRees-ic8jx
    @NicholasRees-ic8jx Рік тому

    I couldn't find documentation anywhere that says what order the arguments to the lamda function from the fold functions. Do you have any idea how I would look this sort of thing up? I was completely lost here, and had to come back to your tutorials to look it up. While your videos are informative and have helped me a lot, they're not great for looking up documentation when you need clarification.

  • @kasapidii
    @kasapidii 4 роки тому +1

    How can I execute isAll on the right way? Don't get it

  • @atesztoth
    @atesztoth 2 роки тому

    Loved the video, thank you!

  • @Drawoon
    @Drawoon 4 роки тому +1

    the names are confusing. foldr starts at the right, but goes to the left. I think it's more intuitive to name it after the direction rather than the starting point, but either way it's confusing.

    • @SamWhitlock
      @SamWhitlock 4 роки тому +2

      Yes it's very mathy and has to do with how the "spine" is evaluated. A better way to think of this is that the accumulator / fixed-point (0 for +, 1 for *, etc) is placed at the right of the list for foldr, and the left for foldl.

    • @michaell8624
      @michaell8624 2 роки тому

      Right and left have nothing to do with the side folding starts or ends. Right stands for right-associative application (of the binary operator/function passed to foldr), and left for left-associative application.
      foldr (-) 0 [1,2,3] will expand to 1 - (2 - (3 - 0))
      foldl (-) 0 [1,2,3] will expand to ((0 - 1) - 2) - 3
      Notice that expansion of the foldl above is identical to 0 - 1 - 2 - 3, because subtraction operator itself is left-associative.

    • @Drawoon
      @Drawoon 2 роки тому

      @@michaell8624 Yeah alright, I suppose that makes sense. In that case I just wish it was more obvious from their names.

  • @bomber5671
    @bomber5671 4 роки тому +4

    This is really great! Thank you so much

  • @mkano7434
    @mkano7434 2 роки тому

    Awsome vid!

  • @bennet5467
    @bennet5467 2 роки тому

    Very helpful. Thanks!

  • @aryansuvarna4923
    @aryansuvarna4923 3 роки тому

    love this video! FOLD IS OP

  • @xetera
    @xetera 4 роки тому +1

    folding without an accumulator would prevent you from doing the first operation, not the last

    • @halbgefressen9768
      @halbgefressen9768 3 роки тому +1

      Depends on the direction of the fold and how you define operation order.

  • @jeffreywbaumann1210
    @jeffreywbaumann1210 3 роки тому +5

    I am struggling with the syntax of Haskell. Besides being phenomenally cryptic and condensed, it appears you are throwing up fragments of code separate from how they would be used in an actual working program (or even complete function block), *and* not explaining what the strange and shifting aggregations of special characters mean. I see "->" and "=>" and "

    • @Tacosnation
      @Tacosnation 2 роки тому +6

      I'd highly recommend rewatching the earlier videos going over syntax, as well as checking out books like "Haskell From First Principles", or the wikibook guide!! Haskell seems a bit opaque at first but it's highly rewarding once you engage with it!!
      Something I've found is that even being given only math education up to calculus, everything we need for functional stuff that lambda calc captures has already been given, it's just implicit and needs to be drawn out!!

    • @AndreiGeorgescu-j9p
      @AndreiGeorgescu-j9p 11 місяців тому

      Maybe you should learn computer science instead of crying. Also he talked about most of this before. You're not gonna to make it far in life if you can't figure out how to watch videos in order. They start with the #1

    • @jeffreywbaumann1210
      @jeffreywbaumann1210 11 місяців тому

      Go Frogs Under Cold Kumquats yourself.@@AndreiGeorgescu-j9p

    • @poorgrammar3136
      @poorgrammar3136 9 місяців тому

      This is #9 so that seems somewhat expected

    • @user-he4ef9br7z
      @user-he4ef9br7z 4 місяці тому

      Skill issue

  • @ProsyMe
    @ProsyMe Рік тому

    fold arrr matey

  • @librarygangster9108
    @librarygangster9108 2 роки тому

    ty a lot !

  • @iswearitsartforsure8493
    @iswearitsartforsure8493 Рік тому

    Good Explanation if you want to understand WHAT it does.
    Not so good to understand how you do it.

  • @MrRys
    @MrRys 2 роки тому +2

    foldr = (x1 op (x2 op (x3 op .... (xn op a))))
    foldl = ((((a op x1) op x2) op x3) ... op xn)
    foldr = x1 op x2 op x3 op x4 ... xn op a works only if it's asociative operation