-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Question / Help] Can anybody explain how to use Free monad? #65
Comments
@expede can you help? |
Hey @hariroshan 👋
http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
I don’t know if I’d start with the free monad when trying to understand the concept of monads broadly. IO is also a bit of a weird case that will not build your intuition. Much ink has been spilled on the topic of “what is a monad / monad tutorial”, but they generally don’t work because there’s an abstraction that’s not obvious until you work with them a bit. The good news is that you can build this intuition pretty quickly, but you need to write some code. I’d work though writing instances for
The TL;DR is that in the same way that
Not sure if this video is helpful for your case, but can’t hurt: https://www.youtube.com/watch?v=psdG5iV57q0 Free MonadIf you’ve ever written an interpreter or a toy languages, the free monad lets you do that in a very clean way. Because DSLs can express literally any domain, it’s a super powerful tool! You also get the added benefit of being able to debug the AST before (or during) running it, which makes debugging incredibly simple. It’s also restricted to your DSL, so it can’t do anything unexpected like sending an unexpected email when your program is for doing DB actions. The free monad takes the “essence” of a monad, and encodes that. You can then embed a functor that describes a DSL that you’re trying to express. This builds up an AST for your DSL (the same general idea as the Elixir AST, but specific to your domain). You then pass this structure off to an interpreter, and as you tear it down, re-run branches (for loops), and adjust the tree of the runtime, you perform effects in the context of the interpreter (e.g. just regular Elixir). The interpreter is a very simple function that has a case for each command in your DSL, and does something with it. This gives you a very very clean, decomposed structure (though at the cost of performance unless you’re in Haskell GHC >= 8.10 with some features enabled). There’s a lot of excitement around free monads right now, because they’re so flexible, are equally expressive as any other monad, are super clean / maintainable. But in Elixir they do with runtime cost (that interpreting+data structure). You can make something similar in a macro (free applicative) and push the performance cost to compile time, but you loose the ability to react/change based on the result of a step — a list instead of a tree. I hope that’s helpful! In my experience teaching a bunch of people these concepts, there’s really no substitute for just rolling up your sleeves and trying out. There’s really nothing comparable that you can build a solid intuition around other than perhaps saying “it’s like JS promises applied to different domains.” It’s a new, different, super powerful way of thinking, in the same way that anonymous functions, pure functions, and actors are super powerful tools. And just like actors, once you understand a monad, they seem obvious — but getting over that first hill is the hardest bit. |
Thank you for your descriptive reply. @expede 👏 🎉 I will practice writing some of the type classes and look through the documentation and code implementation of Algae. I have understanding of
Is this how we use Free monad? Or should we implement our own using Typeclasses? |
I've been search for a good tutorial on understanding this Monad but I'm unable to grasp the concept. I understand how IO monads work. Can anybody explain how to use Free monad to perform
IO
operation orDB
writes withEcto
?Simply explaining with
IO.puts()
is enough.Thanks,
Hari Roshan
The text was updated successfully, but these errors were encountered: