Haskell for Imperative Programmers #38 - Monad Transformers

แชร์
ฝัง
  • เผยแพร่เมื่อ 24 ก.ค. 2024
  • Autobots, roll out!
    More reading:
    wiki.haskell.org/All_About_Mo...
    en.wikibooks.org/wiki/Haskell...
    Timestamps:
    00:00 - Combining IO and Maybe
    02:17 - Maybe Transformer
    05:12 - State Transformer
    08:44 - More Transformers
    09:19 - Transformers are experimental!
    Support me on Ko-fi:
    ko-fi.com/phagenlocher
  • วิทยาศาสตร์และเทคโนโลยี

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

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

    This video series was a life saver dude! I managed to get a Haskell job thanks in part to your great explanations. I still come back for refreshers from time to time

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

      how and where'd you get a haskell job if you dont mind sharing?

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

      @@myxail0 at a Blockchain startup trough linked in

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

      @@bryanfeliciano4102 nice

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

    This is a great series. Thank you for sharing your knowledge to us on Haskell. Eventually, do you have plans to cover the basics for web development with Haskell, using tools such as Yesod, Miso, Scotty, etc. Thank you again!

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

    Another awesome video of this amazing series! Thank you!
    I don't know if the series is still going and if you are taking suggestions on themes for other videos but if you are
    I would love to see your explanation of optics and free monads.
    Also it would be really nice to see an episode dedicated to software architecture in the world of Haskell and FP: how to model the domain, layering, testing, how to separate pure and impure functions in a close to real life project/problem.
    Thanks again for the amazing video and series! I've been learning a lot from it.

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

    Not going to lie.
    I understood the mathematician when he explained it to me. I was lost after your third page. Oddly, I have a very indepth Computer Science background.

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

    Thanks this is the most concise monad transformers tutorial.

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

      I know Im kinda off topic but does anybody know of a good place to watch newly released tv shows online?

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

    You forgot to mention that this is a library.

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

    By the way, and even though, I have lots of question and comments - see below - thank you for the course, which is a good starting point for me.

  • @jyothish-joshi
    @jyothish-joshi 3 ปีที่แล้ว +2

    Amazing content as always!
    If you are taking suggestions on further topics, how about a video, where the alternatives of Monad Transformers can be explored? As Monad Transformers are experimental, as mentioned in this video, it would really help to understand what is the best practice currently as an alternative (probably mtl etc.).
    My other topic suggestions are lenses/optics/best practices (such as why Text instead of String etc.)/Free Monads/real world usecases (eg. Servent based API receiving and serving JSON)/multistage Dockerfile for prod deployment/etc.

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

    In the beginning of the video you give an example of combining IO with Maybe which for some reason ends up in IO Maybe. But why not Maybe IO? This is one of the questions which still bothers me - what’s the intuition behind putting one on top of another and not the other way around? Thanks for your amazing videos!

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

      I'm new to haskell, but I think that's not allowed because you can't have impure IO within Maybe, because mixing pure and impure makes it impure while you can have Maybe within IO, because (IO anything) is already impure.

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

      @@inversebrah This is not the case here. The IO itself is just a value which can be used like any other value. Having IO value doesn’t mean we run the IO, but just keeping some “action description” which can be run in the outside world later on. Therefore, Maybe IO is absolutely legitimate type as such. My question was about nesting order in the context of transformers.

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

      @@andrellow that is generally the reason why composing monads is not trivial and there is no general way to define it. With monad transformers you can choose either order and it will have different semantics. For example composition of Either and Maybe monads may be done as an EitherMaybe or a MaybeEither, which have different semantics. The first one is either an optional value or an error and the second one is an optional result which can be either a value or an error. But the IO monad is a bit special as it has side effects, so binding this Maybe IO computation is tricky or dare I say impossible. E.g. we could interpret IOMaybe as an IO computation that may not return a sensible value. But how should we interpret MaybeIO? A wrapper that means that we may or may not get an IO computation? So lets say we have a sequence of computations mx >>>= f >>>= g. mx is a starter value of our MaybeIO monad, which has some legitimate value, and an IO computation f is done using that value. Now the computation g is such that it results in a Nothing state of our monad. As we specified our monad as a Maybe IO computation, we really should reverse the f computation's side effects, but that's not possible

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

    Question: The code is based on package "transformers". Would you recommend to use "mtl" for a new project or even an effect library?

    • @abhijit-sarkar
      @abhijit-sarkar ปีที่แล้ว

      mtl depends on transformers. For example, MaybeT comes from Control.Monad.Trans.Maybe. Am I missing something?

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

      ​@@abhijit-sarkar
      It has been a long time that I wrote this. I seems that I experimented with the code and figured out that Philipp is using the package "transformers", didn't he? Let's recap.
      package "transformers", documentation on hackage:
      "...Alternatively, it can be used with the non-portable monad classes in the mtl or monads-tf packages, which automatically lift operations introduced by monad transformers through other transformers."
      In transformers exists "Control.Monad.Trans.Maybe".
      package "mtl", documentation on hackage:
      "... MTL is a collection of monad classes, extending the transformers package, using functional dependencies for generic lifting of monadic actions."
      In mtl there is no "Control.Monad.Trans.Maybe", according to the documentation. There is a "Control.Monad.Trans".
      Finally, after all, for me this transformer thing is a to tedious way to work with more complex effects. There is a lots of videos where you see how complcated it can get. E.g.:
      - Zürich Friends of Haskell: Alexis King - “Effects for Less” @ ZuriHac 2020
      - NYC Haskell User's Group: Wrangling Monad Transformer Stacks
      However, question again, if one wants to apply effects inspite all the burden and performance issues: Is it wise to use the extended mtl instead or wouldn't it even better to use an effect library?

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

    Great content as always. If you accept a suggestion, a video on all different kind of textual data types warning about the standard String type versus Text or ByteString would be extremely usefull, specially for beginners.
    Btw: does koofee admits other that PayPal? Or can I contribute economically other way?

  • @sascha-oliverprolic923
    @sascha-oliverprolic923 6 หลายเดือนก่อน

    Just watched this video for the n-th time.

  • @kid-vf4lu
    @kid-vf4lu 3 ปีที่แล้ว

    Do you have a patreon?

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

    Without this tutorial I would fail the Haskell course for sure, thanks a lot.

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

    I'm sorry but this is gibberish for those who don't know Haskell. Seems like people still have no clues how to explain the way Haskell model application logic with its types(compared to object oriented or procedure which are way way more intuitive)

    • @kid-vf4lu
      @kid-vf4lu 3 ปีที่แล้ว +2

      What's your point? Other programming paradigms are easier?

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

      @@kid-vf4lu Definitely. There is no need to discuss the question: how to combine the effects of Maybe and IO in C for example. In other paradigms, there is often no special need to explain such things since it's a direct and intuitive mapping from natural language.

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

      @@nadaxiong Regarding the video being gibberish for people unfamiliar to Haskell: Of course it is. However, I assume that if somebody stuck around for episode 38 or somebody who has never watched the series is interested in monad transformers, they should be familiar with the concepts in this video. You can't learn about monad transformers without understanding monads or types.
      Regarding the comparison to C: Haskell is not supposed to be an easy language to do input-output. In fact, when development started out it didn't even have IO! Haskell is a big "What if?", an experiment to see if a language without side-effects and lazy evaluation could work. The answer: Yes, it can but there is a price to pay. That price is the highly abstract type juggling we have to do. This is where monad transformers are one of the tools we have to combat these issues.
      This high level of abstraction that we have to deal with also provides benefits. Program verification and formal proofs are much easier (let alone possible) in Haskell than in C. Comparing the two languages is a fruitless endeavour anyways since the philosophy behind them is completely different.
      A good video on that topic is th-cam.com/video/iSmkqocn0oQ/w-d-xo.html

    • @kid-vf4lu
      @kid-vf4lu 3 ปีที่แล้ว +7

      @@nadaxiong that's an unnecessarily pedantic point: why does chess exist when checkers is so easy. Functional programming exists because some people find some utility in it.

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

      You should watch the other 37 tutorials then. This series is the best one on youtube. By far. Your comment is nonsense.

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

    The code is not working for me - at least some - or at least I do not know the extra code that has to be programmend. E.g. at 4:35 where is the function "guard" comming from? After lots of trying I convinced the compiler to generate code - however with strange behaviour. Here is the code:
    import qualified Control.Monad.Trans.Maybe as MM
    import qualified Control.Monad.Trans.Class as MC
    import qualified Control.Monad as M
    import qualified Data.Char as Chr
    main :: IO ()
    main = M.void example
    example :: IO (Maybe ())
    example =
    MM.runMaybeT $
    do
    MC.lift $ putStr "please enter your name:"
    sName Bool
    isNameValid [] = False
    isNameValid (ch:_) = Chr.isUpper ch
    getName :: MM.MaybeT IO String
    getName =
    do
    sIn

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

      This area is also in flux but guard presently comes from Control.Monad and has a Bool -> f () signature where f is an Alternative. There are historical reasons… and this generally means a MonadPlus is required to use guard.
      But in the context of monads you can basically think of it as:
      guard True = return ()
      guard False = mzero
      So it simply produces an empty tuple result if the condition used as an argument evaluates to true, and no result otherwise. It’s used to prevent unwanted computations from continuing.
      E.g., list comprehensions (list monad syntactic sugar) turn boolean expressions into guard calls.

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

    I tried to complete the code with respect to the example at 7:40. See the example code below. Is that the way to embed readUntilWithState? See the useless return of nInt.
    import qualified Control.Monad.Trans.State as MS
    import qualified Control.Monad as M
    import qualified Control.Monad.Trans.Class as MC
    import qualified GHC.IO.Handle as IO
    import qualified GHC.IO.Handle.FD as FD
    main :: IO ()
    main = M.void example
    example :: IO Int
    example =
    do
    nInt IO Int
    readUntilWithState sPassword = MS.execStateT (tryToRead sPassword) 0
    where
    tryToRead sPassword =
    do
    MC.lift $ putStr "please enter your password:"
    MC.lift $ IO.hFlush FD.stdout
    nCount