How Monoids are useful in Programming?

แชร์
ฝัง

ความคิดเห็น • 124

  • @badwolf8112
    @badwolf8112 3 ปีที่แล้ว +200

    I THINK FORBIDDING LOWERCASE CHARACTERS WOULD BE A GREAT RESTRICTION.

    • @420moby
      @420moby ปีที่แล้ว +8

      I AGREE WITH THAT STATEMENT

    • @lowlevelcodingch
      @lowlevelcodingch 4 หลายเดือนก่อน +1

      @@420moby TRUE

  • @red_reaper128
    @red_reaper128 5 ปีที่แล้ว +182

    Now that's a epic haskell programming video

  • @valentjedi
    @valentjedi 5 ปีที่แล้ว +108

    I have shown this video to my React codebase. It turned into Elm

    • @MorganEarlJones
      @MorganEarlJones 5 ปีที่แล้ว +23

      I showed this video to my Elm project. It turned into PureScript

    • @asdfghyter
      @asdfghyter 5 ปีที่แล้ว +7

      Nazarii Bardiuk My arch installation has actually gradually turned into NixOS. I’ve basically stopped using pacman now.

    • @MrRedstonefreedom
      @MrRedstonefreedom ปีที่แล้ว

      These kinds of expressions are trivial to do in JS. I've treated predicates in this sort of way in JS probably a couple hundreds of times. You can even implement a pipe() like haskell's "do" with like three LOCs. Although unlike lisp you can't define your own syntax to go along with the implementation :((( , but i don't think haskell can do so either.

    • @user-tx4wj7qk4t
      @user-tx4wj7qk4t 5 หลายเดือนก่อน

      ​@@MrRedstonefreedomyou have monoids in js? And not sure how do is relevant or how any of this is "trivial" when the average js dev can't even go outside without a helmet

  • @joriskbos1115
    @joriskbos1115 3 ปีที่แล้ว +44

    Whenever he says "what do I need for that?" The answer is always a function

  • @greob
    @greob 5 ปีที่แล้ว +38

    This is beautiful. Maybe you'd want to mention "Haskell" in the video title, for people looking for tips in Haskell specifically.

    • @meneereenhoorn
      @meneereenhoorn 4 ปีที่แล้ว +1

      For Haskell come to Tsoding.

  • @gillchristiang
    @gillchristiang 4 ปีที่แล้ว +143

    "that looks like something and average javascript programmer would write and is extremely lame"
    lmfao this is why I watch your videos (oh and yeah I work with JS for a living)

    • @kamilzielinski1303
      @kamilzielinski1303 3 ปีที่แล้ว +1

      same

    • @Metruzanca
      @Metruzanca 2 ปีที่แล้ว

      I'm here to learn how to use monoids in my JavaScript.

    • @snapman218
      @snapman218 2 ปีที่แล้ว +1

      JS can burn in hell

  • @LeoOno
    @LeoOno 4 ปีที่แล้ว +14

    following the logical sequence of your thought to arrive at the final composite function of all predicates using monoids was amazing, very enlightening so thanks a lot :)
    !

  • @BryceTheGrand
    @BryceTheGrand 5 ปีที่แล้ว +72

    You could just create a function "f = (or .) . sequence"
    This is a function that when given a list of functions of type [Char -> Bool] it returns a single function of type Char -> Bool.
    This uses Monads by pulling "Char ->" outside of the list and returning a list of [Bool], which then uses "or" to see if one is true.
    Or, to get it all in one line:
    isForbidden = or . sequence [isBraille, isDigit, isUpper]

    • @noomade
      @noomade 4 ปีที่แล้ว +8

      this is really nice . thanks!
      i had been using `foldr1 (liftA2 (||)` before this
      I am curious as to how the compiler optimises your code

    • @dirrelito
      @dirrelito 3 ปีที่แล้ว +3

      But that is monad. Not monoid. So it undermines the point of the video?
      ...but i agree it is the more "natural" code.

    • @micknamens8659
      @micknamens8659 2 ปีที่แล้ว +3

      @@noomade Due to lazy evaluation the code (isForbidden = or . sequence [isBraille, isDigit, isUpper]) should work out-of-the-box (i.e. w/o compiler optimization) quite straight.

    • @maxmuller445
      @maxmuller445 ปีที่แล้ว +12

      @@dirrelito a monad is a monoid in the category of endofunctors. So it is still a monoid too

  • @MrRedstonefreedom
    @MrRedstonefreedom ปีที่แล้ว +7

    If I ever pickup haskell, I saved this video since it's the fastest whirlwind tour of almost every aspect of the language environment 😂 -- in under 10 minutes!
    help system, errors, composition, libraries, it's got it all

  • @7robertodantas
    @7robertodantas 5 ปีที่แล้ว +4

    I've been learning a lot from you! Your videos are great! Congrats! 👏👏👏

  • @2003vito
    @2003vito 5 ปีที่แล้ว +18

    Breathtaking

  • @fakt7814
    @fakt7814 4 ปีที่แล้ว +7

    I knew about such a powerful tool as monoids before but I didn't know that any function that returns a monoid is also a monoid and it can be used in a very predictable way. Thank you.

  • @user-ss7eh7xf1b
    @user-ss7eh7xf1b 5 ปีที่แล้ว +21

    More Haskell videos, they are so epic!

  • @jamma246
    @jamma246 5 ปีที่แล้ว +4

    These are the best Haskell tutorials I've seen!

  • @aBamieh
    @aBamieh 5 ปีที่แล้ว +6

    Cool, i get so excited when you post haskell content

  • @BrianMcKennaPuffnfresh
    @BrianMcKennaPuffnfresh 5 ปีที่แล้ว

    Really good stuff!!! ♥️

  • @carlost23489
    @carlost23489 5 ปีที่แล้ว +2

    Outstanding!!!

  • @v01d11
    @v01d11 5 ปีที่แล้ว +2

    The Crazy Train mix at the end makes this video even more epic :)

  • @tahamagdy4932
    @tahamagdy4932 5 ปีที่แล้ว

    Stunning!

  • @smuecke
    @smuecke 5 ปีที่แล้ว +11

    Why the hassle with importing stuff?
    isForbidden c = any $ map ($ c) [isBraille, isEmoji]

    • @Kennnn264
      @Kennnn264 4 ปีที่แล้ว +4

      Why the map?
      isForbidden c = any ($ c) [isUpper, isDigit]

    • @bratezoran2102
      @bratezoran2102 3 ปีที่แล้ว +4

      @@Kennnn264 why the function parameter? `isForbidden = or . () [isUpper, isAlpha] . pure`

    • @aurorazuoris6654
      @aurorazuoris6654 3 ปีที่แล้ว +2

      isForbidden = or . sequenceA [isBraille, isEmoji]

  • @WilcoVerhoef
    @WilcoVerhoef 3 ปีที่แล้ว +4

    *isForbidden c = any ($c) [ isEmoji, isBraille ]*
    I don't like importing lesser known functions when the alternative is just as concise.

  • @japrogramer
    @japrogramer 5 ปีที่แล้ว +15

    I used to Haskell but than I took a python to the knee.

  • @seethruhead7119
    @seethruhead7119 3 ปีที่แล้ว

    Really good explanation love it

  • @telnobynoyator_6183
    @telnobynoyator_6183 4 ปีที่แล้ว +1

    *the bot took a huge coredump*
    Love it !

  • @Tomyb15
    @Tomyb15 10 หลายเดือนก่อน +2

    Apart from the other nice solutions or variations that have been outlined here in the comments, I wanted to mention that there is no need to fmap a newtype data constructor just to satisfy the type checker, given that newtypes are a no-op at runtime. All newtype instances are coercible with their underlying type, so you should be able to use the ```coerce``` function from Data.Coercible to turn them into Any or All with no runtime cost.
    You probably need some type signature to clarify which instance to coerce into. Something like ```(coerce :: [a -> Bool] -> [a -> Any])``` or better yet
    ```isForbidden = getAny . (fold $ coerce predicates :: Char -> Any) where ...```

  • @buncha1499
    @buncha1499 3 ปีที่แล้ว

    Your videos are gold

  • @AK-vx4dy
    @AK-vx4dy 9 วันที่ผ่านมา

    Respect... you really understad Monads and solid chunk of Haskell 🤯

  • @davidyanceyjr
    @davidyanceyjr 4 ปีที่แล้ว

    indeed that was a predicool video.

  • @wlcrutch
    @wlcrutch ปีที่แล้ว

    Impressive! 👍🏻

  • @comarnicolodi
    @comarnicolodi 4 ปีที่แล้ว +2

    Your channel is too good to be true

  • @0nus1
    @0nus1 7 หลายเดือนก่อน +1

    Shame the epic functional Tsoding compsoy days are over - these videos were the best advertising Haskell has ever had

  • @ooloncolluphid9975
    @ooloncolluphid9975 4 ปีที่แล้ว +1

    EPIC!

  • @moy4604
    @moy4604 ปีที่แล้ว

    mind blowed video!

  • @steffahn
    @steffahn 4 ปีที่แล้ว +2

    Lol, I read the title as referring to Monads and thought you might be aiming for something like "or . sequence predicates"

  • @raphipik
    @raphipik 2 ปีที่แล้ว

    I fucking love you! Thanks for this video!

  • @AndrewBrownK
    @AndrewBrownK 5 ปีที่แล้ว +38

    I think the "m" in "mempty", "mappend", and "mconcat" stands for "M"onoid

    • @WillBergson
      @WillBergson 4 ปีที่แล้ว +11

      the thing is why it is empty and append for an identity and a binary operation

    • @arthur-vi1ub
      @arthur-vi1ub 3 หลายเดือนก่อน

      That's a reference to the corresponding list operators, lists being the canonical monoid (also called the Free monoid)

  • @hubstrangers3450
    @hubstrangers3450 3 หลายเดือนก่อน

    Thx

  • @EduardoRFS
    @EduardoRFS 5 ปีที่แล้ว +3

    I will someday became an Epic haskell developer

  • @ash__borne
    @ash__borne 6 หลายเดือนก่อน

    It's crazy to see that you've been doing crazy sh#t for so long 😂

  • @Zorgatone
    @Zorgatone 4 ปีที่แล้ว

    Name of the outro song?

  • @leyliramazanova4201
    @leyliramazanova4201 3 ปีที่แล้ว

    damn, this is good

  • @random-characters4162
    @random-characters4162 ปีที่แล้ว

    very entertaining btw

  • @nevokrien95
    @nevokrien95 3 หลายเดือนก่อน +1

    This is so bizarre he changed his tune so much

  • @FunkschyIsWatchingYou
    @FunkschyIsWatchingYou 5 ปีที่แล้ว +1

    Pog

  • @aedd3307
    @aedd3307 3 ปีที่แล้ว +1

    did u just say that ascii art uses unicode characters?

  • @RunningRay9
    @RunningRay9 2 ปีที่แล้ว

    Epic

  • @meneereenhoorn
    @meneereenhoorn 4 ปีที่แล้ว

    Epic haskell programmer move.

  • @alkouille2794
    @alkouille2794 4 ปีที่แล้ว

    ya so epicc

  • @DanDart
    @DanDart 4 ปีที่แล้ว

    Seems like you could continue this by explaining contravariants.

  • @cynocephalusw
    @cynocephalusw 3 ปีที่แล้ว +1

    „Max“ turns out to be a Join Semilattice, because it suffices idempotence.

  • @pdr.
    @pdr. 5 ปีที่แล้ว +9

    Why not just map the argument to the predicates and use "or"?

    • @jadissa3841
      @jadissa3841 5 ปีที่แล้ว +6

      I'd use:
      isForbidden x = any $ map ($ x) predicates

    • @asdfghyter
      @asdfghyter 5 ปีที่แล้ว +8

      Then you don’t get to use monoids. :P

    • @jadissa3841
      @jadissa3841 5 ปีที่แล้ว +3

      @@asdfghyter I've used monoids in better ways before. You should get yourself the best, clearest solution not the one that uses monoids

    • @abhishekkadam2999
      @abhishekkadam2999 5 ปีที่แล้ว +12

      Because, that won't be a "epic Haskell developer move" 😆😆

    • @pdr.
      @pdr. 5 ปีที่แล้ว

      @@jadissa3841 Yeah exactly. I meant "any" not "or".

  • @sebastiangudino9377
    @sebastiangudino9377 ปีที่แล้ว

    Sadly this is no longer written in Haskell, he recently changed it to Go :(

  • @teliph3U
    @teliph3U 5 ปีที่แล้ว +1

    foldMap all the things.

  • @nono1271
    @nono1271 4 ปีที่แล้ว +1

    In JavaScript this is just
    const predicates = [isNumeric, isLower];
    const isForbidden = char => predicates.some(p => p(char));

    • @bratezoran2102
      @bratezoran2102 3 ปีที่แล้ว +2

      ...and in haskell you can use the same concept: `isForbidden char = any (\p-> p char) [isUpper, isNumber]`.
      And then you can further simplify, which does not work in JS: `isForbidden char = any ($ char) [isUpper, isNumber]`.
      ;)

  • @PS3PCDJ
    @PS3PCDJ 2 ปีที่แล้ว +1

    So this is how normal people feel when they see someone reason about code to implement

  • @Nathankthanks
    @Nathankthanks 4 ปีที่แล้ว

    Maybe Works

  • @mechmaker9346
    @mechmaker9346 5 ปีที่แล้ว

    monoids it's good,but i don't know,how i can apply it in other situations.

  • @mvmo4744
    @mvmo4744 5 ปีที่แล้ว

    🦄

  • @blitzritz
    @blitzritz 4 ปีที่แล้ว +1

    Can you please do a video on Monad Transformers and Free Monads? Please! Pretty Please! You simply are the best Haskell teacher I have ever come across.

  • @blocktech26
    @blocktech26 ปีที่แล้ว

    fuck I love haskell

  • @arisweedler4703
    @arisweedler4703 3 ปีที่แล้ว +3

    I understand that a monoid is a function that takes type T, T as input and returns type T as output, and I understand how it is thus necessary to give a fold/reduce/whatever higher order function a monoid.
    I did not understand this at first, but a second watch cleared things up! Here is my understanding, in my own words.
    The mathematical concept of a "boolean" is clearly a monoid. But haskell is a strongly typed language! And the haskell type Bool is NOT a monoid. Luckily, there exists a class that fixes this problem. It effectively extends Bool. (Really, it wraps it, but I don't know Haskell so idk if you can extend classes. You can't in C++, you can in something like ruby. I'm being too imprecise to be nuanced here...). And it extends Bool in a way s.t. it is a monoid! So you can use it in fold.
    Thus, you need to map to wrap so you can fold then unwrap to get your answer. GG

    • @KohuGaly
      @KohuGaly 2 ปีที่แล้ว +5

      A monoid is a mathematical object. It's a pair of set and a binary operation, that satisfies certain properties. The operation needs to be closed (ie. it always returns members of the set, when it has members as the inputs) and there's neutral element (ie. there's an element for which applying the operation to any other member, just gives back that member).
      Examples of monoids:
      Integers with addition - neutral element is 0.
      Integers with multiplication - neutral element is 1.
      lists with concatenation - neutral element is empty list.
      Boolean on its own is not a monoid, because it is not specified which operation is should be monoid to. Both logical AND and OR form a monoid over Boolean (just like integers are monoid under both addition and multiplication).
      This is where traditional OOP really sucks at expressing these concepts. It reinvents the wheel, but makes it square and puts the axis at an angle. A monoid can be thought of as a virtual class, that has one virtual field (the data type you are monoiding over) and a virtual function with two inputs and output, all of the Self class (this is the binary operation).

  • @danielsmith5626
    @danielsmith5626 3 ปีที่แล้ว +2

    i like how there's an efficient solution 1:25 into the video but it's scrapped for epic haskell hubris

  • @iskuchekov
    @iskuchekov 5 ปีที่แล้ว

    much epic such uwu! that was really cool

  • @DanDart
    @DanDart 5 ปีที่แล้ว +1

    Instinctively I'd have just gone the applicative route, so something like this:
    or $ "w" [isUpper, isLower]

    • @noomade
      @noomade 4 ปีที่แล้ว +2

      your function is not the same thing ... it is String -> Bool ... and we want Char -> Bool... so you only need functor `or $ ($ 'w') [isUpper, isLower]`
      or if you must with applicative `\w -> or $ pure w [isUpper, isLower]`

    • @bratezoran2102
      @bratezoran2102 3 ปีที่แล้ว

      @@noomade ah didn't see someone else used applicative and posted another comment. OPs code compiles, but your code doesn't. I'm curious what you did with the lambda after the `or`, haven't seen that before.
      I just know this way: `isForbidden c = or $ () [c] [isUpper, isLower]`. btw, works also without importing Control.Applicative and pointfree like so: `isForbidden = or . () [isUpper, isAlpha] . (:[])`.

    • @noomade
      @noomade 3 ปีที่แล้ว

      @@bratezoran2102 Hi, to be honest I don't remember what I was trying to do. Looks like a comedy of errors (but maybe there was something that I just can't think of right now). I think I probably meant simply `\w -> or $ pure w [isUpper, isLower]`
      and the point free of the functor only would be ` or . () [isUpper, isAlpha] . pure`.
      Thanks for pointing it out. If I remember anything else later. I'll @ you. but I have edited my original post for now.

    • @bratezoran2102
      @bratezoran2102 3 ปีที่แล้ว

      @@noomade ah right, now it makes sense! the code works now. thought this was some kind of special usage of `or` with a lambda. thanks for your reply anyway.

  • @v__802
    @v__802 5 ปีที่แล้ว +2

    Also you can coerce predicates, so
    isForbidden = getAny.mconcat predicates where predicates = coerce [isLower,isDigit]

  • @j22n3s
    @j22n3s 4 ปีที่แล้ว

    Are you a magician ?

  • @mechmaker9346
    @mechmaker9346 5 ปีที่แล้ว

    I love haskell vert much....
    Please...
    Make video about chat bot on haskell...

    • @123coolmik
      @123coolmik 4 ปีที่แล้ว +1

      Mech Maker watch the twitch live streams, he has a pre-planed schedule for them.

  • @gregbell2117
    @gregbell2117 5 ปีที่แล้ว +5

    It seems that a lot of the point of Haskell is to learn more and more abstract concepts to write code that's a little shorter, or a little weirder. I like it, but I feel that if I wrote code like this, I should probably be fired.

    • @beauteetmusculation8191
      @beauteetmusculation8191 2 ปีที่แล้ว +2

      Actually, the examples here aren't great to understand the beauty of functional programming. In practice, the code is way shorter, and you chose if you want to make it even shorter by requiring reviewers more intimate knowledge of the language or not.

  • @Kennnn264
    @Kennnn264 4 ปีที่แล้ว

    m'onoid

  • @lm1338
    @lm1338 2 ปีที่แล้ว +38

    So this mainly shows that monoids are a really complicated way of doing extremely primitive things.

    • @kinjalbasu1999
      @kinjalbasu1999 ปีที่แล้ว +13

      Please also consider the reduction in lines of code and extensibility (here, the ability to add more conditions easily).

    • @Heater-v1.0.0
      @Heater-v1.0.0 10 หลายเดือนก่อน

      @@kinjalbasu1999 Reduction in lines of code is not a good argument. A program reduced. to a few lines of cryptic symbols and unfathomable keywords becomes as readable/understandable as a text file being zipped.
      The ability to add more conditions easily is not a good argument, we could do that with a list of functions in almost any language.

    • @thoriqadillah7780
      @thoriqadillah7780 8 หลายเดือนก่อน +1

      ​@@Heater-v1.0.0well i think this monoid has been used widely in http framework, which is middleware.
      Adding more middleware easily in form of list in our handler is big

    • @Heater-v1.0.0
      @Heater-v1.0.0 8 หลายเดือนก่อน

      @@thoriqadillah7780 Indeed. I think I start to get it then. This "monoid" thing is what C programmers call a a "call back". After all web servers have been allowing for the insertion of middleware since forever and I don't recall that ever being called a monoid.
      Luckily we don't need to use Haskel to make use of such a pattern. Almost any language will do.

  • @bratezoran2102
    @bratezoran2102 3 ปีที่แล้ว

    Or with Applicative: `isForbidden = or . () [isUpper, isAlpha] . pure`

  • @DjLeonSKennedy
    @DjLeonSKennedy 4 ปีที่แล้ว

    Could u explain Profunctor Optics in practice ? Please!!!!!!)

  • @eduardoarandah9990
    @eduardoarandah9990 ปีที่แล้ว

    str.includes() and you’re done. Why things have to be so complicated?

    • @sebastiangudino9377
      @sebastiangudino9377 ปีที่แล้ว +2

      This is a bit more complicated. Since you are actually combining functions that detect characters, not just character themselves. So while it doesn't make sense I'm this context, it will be easy to extend with mor abstract predicates (Compilers and parsers written in languages like Haskell make heavy use of this kind of things)
      So while seemingly complicated this is actually very generic and elegant! And Haskell tends to reward elegance with Maintainability and Performance increases
      But yeah, I totally get that the barrier of entry is absurdly hard. And if you have no good reason to learn Haskell I would simply not recommend it. You will speed a looooot of time with very little in return

  • @andreasschau4215
    @andreasschau4215 ปีที่แล้ว

    Javascript script-kiddies gonna hate this trick... 😅

  • @stephenkamenar
    @stephenkamenar 5 ปีที่แล้ว +16

    that's what i call over engineering

  • @ulissemini5492
    @ulissemini5492 5 ปีที่แล้ว +5

    you way overdid it, all you needed was
    import Data.Char
    isForbidden :: Char -> Bool
    isForbidden c = any (\f -> f c) predicates
    where predicates = [isLower, isDigit]
    or to be slightly shorter
    any ($ c) predicates

  • @MrRedstonefreedom
    @MrRedstonefreedom ปีที่แล้ว

    I appreciate the explanation, it's very cool to see! Though much the same is possible in any other language, without the needless mathematics terminological specificity.
    You maligned javascript for example, but this is a trivial implementation in javascript. Functions are objects and so you can likewise describe a "noneOfAnyOfPredicates(particular Predicates)" and simply define the predicates by virtue of a constant value type.
    Compositionality is not a new thing to uniquely Haskell, and in fact it seems quite a bit easier to express without this extra complexity baggage of "getAny" (rather misleading, and annoying boilerplate imo) or the info-doc lookups you had to do for whether haskell's arbitrary definition of boolean classified it as a monoid or not.
    Again, the video is great, it's just that one small point you made 2x was just flatout wrong. JS is not limited in this respect. In fact if anything, JS isn't limited at all, besides things like macros like you get out of lisp, but I don't think haskell has anything close to it. its problems come from the lack of limitation. or maybe with haskell, if you're doing mathematical proofs, stuff like abstract properties of the operations and maybe operator overloads though i don't really know enough about haskell to say one way or another.

    • @samuraijosh1595
      @samuraijosh1595 6 หลายเดือนก่อน +1

      you have no idea what youre talking about JS kiddo

  • @AlexKavanagh29x
    @AlexKavanagh29x 5 ปีที่แล้ว +5

    I suspect this is "doing it for the sake of doing it because it is clever". "isDigit x || isUpper x" is much more readable that using the Monoid. If you really want to be "pointless" you could also do the slightly less obvious "(||) isDigit isUpper". Just because you can, doesn't necessarily mean you should.

    • @Tsoding
      @Tsoding  5 ปีที่แล้ว +6

      Works only with two predicates.

  • @newborn7348
    @newborn7348 3 ปีที่แล้ว

    An epic USELESS move!

  • @DryBones111
    @DryBones111 2 ปีที่แล้ว

    You could achieve the same result with:
    isForbidden c = any ($ c) predicates
    I'm not sure which approach I prefer however, the monoid approach is pretty cool.