Secret Haskell Composition Technique

Поделиться
HTML-код
  • Опубликовано: 27 дек 2024

Комментарии • 76

  • @arturjorge5607
    @arturjorge5607 4 года назад +51

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

  • @rexcfnghk
    @rexcfnghk 4 года назад +97

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

  • @GotoFail
    @GotoFail 4 года назад +130

    Tsoding is the king of penetration

    • @nilp0inter2
      @nilp0inter2 4 года назад +11

      And double penetrantion as well

    • @EidosGaming
      @EidosGaming 4 года назад +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

  • @stintaa
    @stintaa 6 месяцев назад

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

  • @SimGunther
    @SimGunther 4 года назад +8

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

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

  • @CARDCZARMAFIA
    @CARDCZARMAFIA 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 года назад +47

      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 4 года назад +8

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

  • @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 4 года назад +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

  • @maximkovalkov1334
    @maximkovalkov1334 4 года назад +1

    inb4 this gets demonetized for "double penetration"

  • @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?

  • @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.

  • @AryadevChavali
    @AryadevChavali 4 года назад +8

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

  • @web3tel
    @web3tel 4 года назад +5

    why not newtype Compose , bljat'?!

  • @hubstrangers3450
    @hubstrangers3450 2 месяца назад

    Thank you....

  • @余淼-e8b
    @余淼-e8b 3 года назад

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

    • @Egzvorg
      @Egzvorg 2 года назад

      That's emacs

  • @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).

  • @davidyanceyjr
    @davidyanceyjr 4 года назад +2

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

  • @agivney
    @agivney 4 года назад +3

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

  • @quintencabo
    @quintencabo 10 месяцев назад

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

  • @DanDart
    @DanDart 4 года назад +6

    2:26 succ

  • @thinkbait8363
    @thinkbait8363 4 года назад +1

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

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

  • @Hammaddev-b3j
    @Hammaddev-b3j Год назад

    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 Год назад +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

  • @johannbauer2863
    @johannbauer2863 4 года назад +1

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

  • @JaimePascual
    @JaimePascual 4 года назад +1

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

  • @СергейКузнецов-в8ю7ш
    @СергейКузнецов-в8ю7ш 4 года назад +1

    Yay! Haskell it is!

  • @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.

  • @alurma
    @alurma 4 года назад

    nice. glad i subscribed half a year ago

  • @nerkulec
    @nerkulec 4 года назад

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

  • @valcron-1000
    @valcron-1000 4 года назад +2

    That intro tho...

  • @lclutz
    @lclutz 4 года назад +3

    amazing intro 😂

  • @daviddawkins
    @daviddawkins 4 года назад

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

  • @kohlensaurerulpser2595
    @kohlensaurerulpser2595 4 года назад +1

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

  • @bernardostearns9696
    @bernardostearns9696 4 года назад

    this guy is the best

  • @gdargdar91
    @gdargdar91 4 года назад

    Monads don't compose lol

  •  2 года назад

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

  • @skyfall-t8p
    @skyfall-t8p 4 года назад +5

    fmap = fmap . fmap
    pure = pure . pure
    😜

    • @Bratjuuc
      @Bratjuuc 2 года назад

      liftA2 = liftA2 . liftA2

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