Secret Haskell Composition Technique

แชร์
ฝัง

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

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

    "You still perform double penetration, but you hide it from the user"
    - - Tsoding

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

    Tsoding trolling us by asking us to implement the composition of monads 🤣

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

    Tsoding is the king of penetration

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

      And double penetrantion as well

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

      @@nilp0inter2 fmap . fmap so?

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

    I love how you use the word "secret" to make this video more appealing to click on

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

    the bottom of the screen says "Porn Folder: 43.9 GiB"...that's not nearly enough, man.

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

      too smol PepeHands

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

      Well there are a lot of penetrations and double penetrations in the video

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

    "Injecting" things is how we get endofunctors. Truly the mathematical way of doing compositions and metaprogramming.

  • @stintaa
    @stintaa 28 วันที่ผ่านมา

    Rewatching your old videos, and this intro hit as hard as it did 4 years ago :D

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

    Rust values can be mapped. It's pretty easy to implement a functor trait. Unwrap is actually a code smell

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

      You can't do it generically though because Rust doesn't support higher-kinded types, which means no fmap. There's a big GH issue to bring HKTs to Rust one day so the Rust community can start writing monad tutorials like "A monad is just a shell exchanging crabs bro what's the problem???"

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

      it's impossible to implement a functor trait in Rust, as of now.

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

    Thanks for another great video, maybe a tut about haskell memoization for us mere mortals. This mortal is struggling.

  • @user-ss7eh7xf1b
    @user-ss7eh7xf1b 4 ปีที่แล้ว +1

    Yay! Haskell it is!

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

    nice. glad i subscribed half a year ago

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

    Ah hell yea so that's how you use it!
    How about triple without fmap?
    Maybe one on transformers / free monads or effects to help "compose" monads?

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

    text version of would be called "apply".
    if you're talking about the specific operator I call it the spaceship operator

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

      That might be confused with the spaceship operator in languages like Perl, .

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

      @@variadicism1047 not likely!

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

    "In Rust you unwrap everything"
    Oh yeah?
    fmap (\x -> x + 1) (Just 5)
    is written
    Some(5).map(|x| x + 1);
    in Rust
    no unwrap required.

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

      I dont think he was saying you can't but that devs often don't. I've seen this in other languages like java

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

      @Sydney Bean the question mark operator is just monadic bind in the context of optionals. It performs the exact same function

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

      @Sydney Bean
      Point is:
      fn test1() -> Option {
      let a = may_fail()?;
      let b = may_also_fail()?;
      Some(a + b)
      }
      is the same as
      fn test2() -> Option {
      may_fail().and_then(|a| may_also_fail().map(|b| a + b))
      }
      play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d5e6fa175cdba9bc18b108c98f828124

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

      @@NikolajLepka how would this look like in Haskell?

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

      @@chaoky the link I posted in the comment has the Haskell versions written in comments

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

    this guy is the best

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

    You can (and should) use map on Option in Rust

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

    amazing intro 😂

  • @valcron-1000
    @valcron-1000 4 ปีที่แล้ว +2

    That intro tho...

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

    why not newtype Compose , bljat'?!

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

    yay i wanna be on the list of people at the end

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

    2:31 "b-but alexey w-we haven't even been on a date yet..."

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

    Another great tutorial. The only thing; my brain hurts.

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

    2:26 succ

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

    inb4 this gets demonetized for "double penetration"

  • @quintencabo
    @quintencabo 5 หลายเดือนก่อน

    20:13 g that contains b, that just made so much things click!

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

    I'm following allowing in VS Code, and I'm curious why the linter included with the haskell extension is recommending `newtype` instead of `data`. Do you have an opinion Tsoding?

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

      in this case newtype is better because it essentially creates a wrapper for your types which exists only in design time and is stripped in runtime. so by using newtype you aren't creating new entities, just referencing the same types and implementing different interfaces for them

  • @user-xm9xo7jg4u
    @user-xm9xo7jg4u 2 ปีที่แล้ว

    What the text editor are you using? It looks so cool.

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

      That's emacs

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

    This is a very nice and elegant solution. However it's a little bit unsatisfactory that it only wraps two functors at a time... is there a way to declare a recursive datatype that fmaps over an arbitray length of composition? A little bit like the free monad

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

      You could nest the compose. Then the outer compose uses the fmap of the inner one in its fmap, so everything would work automatically.

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

      ((+1) ) (map Just [0..4]) gives [Just 1,Just 2,Just 3,Just 4,Just 5]

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

      @@JaycenGiga Yes, but then to get the inner value you'd need to know how long the chain is.

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

      @@kriswright5112 I'm sorry but I don't understand what you're trying to say. You've just switched the two functors

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

      @@SomeMrMindism i don't know what I'm trying to say either. the only recursive datatype I know in Haskell is Tree. Maybe you could do something like the Functor Tree example from learnyouahaskell but instead of left and right branches, just do a right branch. don't know. I'm just learning Haskell.

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

    ...Next train to "JSON Parser" station departs in 26 minutes 44 seconds from "Tsoding Channel" platform...

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

    I know you are partiality joking about Rust developers unwraping everything, but there do exist functor and monadic functions in rust for Option, Result, and other types and should be used along with the try operator when you need use wrapped values (much like do notation).

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

    If this channel needs one thing, it's regular scheduling

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

      See tsoding daily

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

      I know that you wrote it 3 years before

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

    That was great, thank you! Now, I thought `bind` was *exactly* a composition of monads? The comments here suggest otherwise.

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

    "Rust developers must constantly unwrap everything."
    Uh... we have Option::map and Either::map_ok. Sure, they're not typeclasses, but they're still quite composable.

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

    I thought monads do not compose in general.. edit ok just saw the description of the vid lol

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

    Monads don't compose lol

  • @user-ck1kx5ie6t
    @user-ck1kx5ie6t 4 ปีที่แล้ว +5

    fmap = fmap . fmap
    pure = pure . pure
    😜

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

      liftA2 = liftA2 . liftA2

  •  2 ปีที่แล้ว

    damn - I really want to share this with my co-workers but it's clearly NSFW

  • @user-yj4xq6ix5n
    @user-yj4xq6ix5n 11 หลายเดือนก่อน

    it bothers me soo much that the type signature of
    is
    () :: Functor f => (a -> b) -> f a -> f b
    and not
    () :: Functor f => f a -> (a -> b) -> f b
    with the second signature we could've written beautiful code like
    foo :: Functor a -> Functor b
    foo x = x
    func1
    func2
    func 3
    just like the monad >>= operator

    • @drdilyor
      @drdilyor 9 หลายเดือนก่อน +2

      you can use for exactly that. is defined that way to be similar to $. is also similar to &.
      is defined in Data.Functor, & is defined in Data.Function

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

    defining liftA2 instead of () for Compose is much easier and intuitive
    instance (Applicative f, Applicative g) => Applicative (Compose f g) where
    pure = Compose . pure . pure
    liftA2 f (Compose a) (Compose b) = Compose $ (liftA2 . liftA2) f a b