opened
hariroshan
username_0
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 or `DB` writes with `Ecto `?
Simply explaining with `IO.puts()` is enough. 
Thanks,
Hari Roshan
[Question / Help] Can anybody explain how to use Free monad?
issue
created
hariroshan
username_0
@username_1 can you help?
comment
created
expede
username_1
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 `Identity`, `List`, `Either`, and `Writer` from scratch. This means implementing the following type classes (fancy super protocols provided by Witchcraft) for each of them:

* Functor
* Apply
* Applicative
* Chain
* Monad

The TL;DR is that in the same way that `map` lets you apply a function to every element in some container without changing its structure (that’s `Functor.map`, not `Enum.map`), “monad” is an abstraction over things that have some pure “effect” automatically book-kept by the instance. If you’re familiar with JS, Promises are the kind of “effect” that I’m talking about. It turns out that when you look at the structure of lots of computations, there’s similarities, even though the surface details are different (which is just “abstraction”). This means that you can then write code once, and then run it in any monad and have it take care of different things for you. For example:

* Writer — log messages to a store that is invisibly kept next to the data it references. You can send the data and log across the wire, persist them to disk and resume later, just debug the path that got you to some state, and so on.
* Either — totally pure version of `with` (automated error handling)
* State — a totally pure equivalent to an `Agent` (and because it’s restricted as pure you can have an impure implementation that’s say, based on Agent or even RAFT without needing to change your code just, the specialized monad that it’s running in)
* List — the effect of running the same functions (plural!) over multiple inputs (also plural). Sometimes call the indeterminacy monad
* Many, many more

Not sure if this video is helpful for your case, but can’t hurt: https://www.youtube.com/watch?v=psdG5iV57q0

# Free Monad

If 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.
comment
created
hariroshan
username_0
Thank you for your descriptive reply. 👏  🎉   I will practice writing some of the type classes and look through the documentation and code implementation of Algae. I have understanding of `map/2`, `apply/2` and `bind/2 / chain/2`. I know how to Either and Maybe well enough to do **Railway Oriented Programming**. 
I learned most of the concepts from **Professor frisby's mostly adequate guide to functional programming** book. In this he implemented IO monad approximately as
`IO.of( ( unit -> any ) ) :: {:io, ( unit -> any )}`
`map/2` and `bind/2` are implemented as function compositions. Finally, he uses a `run/1` function to execute the IOs. Thus making the caller to decide whether to execute side effects or not. Is this how we make impure functions to pure functions by making them return an option IO ?
For example
`add(integer, integer) :: {integer, Maybe.t(IO.t())} `
Also I tried executing similar things with Free monad in IEx. It does take a function and composes them while mapping. 
For example I have,
```

  @spec initialize ::
          Free.Roll.t(
            ({ipAddress, port_number()} ->
               Either.t(
                 :gen_tcp.reason() | String.t(),
                 port
               )
            )
          )
  def initialize do
    Free.free(fn {ip, port_number} ->
      @infrastructure.testConnection(ip, port_number)
      |> bind(fn connected_port ->
        Port.close(connected_port)
        @infrastructure.start_connection(getPortJSPath())
      end)
      |> map(fn port ->
        port
        |> @infrastructure.sendValue(0)
        |> @infrastructure.sendValue(
          {:init, %{"ip" => ip |> to_charlist, "port" => port_number}}
        )
        port
      end)
    end)
  end
```

Is this how we use Free monad? Or should we implement our own using Typeclasses?
I hope I'm not bothering
Thanks,
Hari Roshan 😄
comment