A few questions about Monad implementation

I follow some tutorials online and practice to implement a basic Monad type as below. Now I have a few naive questions.

First, is this implementation functional complete? From what I read as this implementation fulfills the monad laws. So it should be functional complete (in terms of Monad type) the same as e.g. Monad provided in Cats lib, right? If not, what is missing? I understand Monad provided in the lib like Cats is far superior and functional feature rich, but I merely want to ensure if I understand the basic ideas correctly.

  • Left identity: Monad(x).flatMap(f) == f(x)
  • Right identity: Monad(x).flatMap(Monad(_)) == Monad(x)
  • Associativity: Monad(x).flatMap(f).flatMap(g) == f(x).flatMap(g)

Second, if I want to apply this Monad to my production project, anything that is missing? This question is a bit like edge cases that I also need to consider; not attempting to compare the lib such as Cats.

Many thanks.

object App {
  object Monad {
    def apply[A](value: => A): Monad[A] = new Monad(value)
  }
  class Monad[+A](value: => A) {
    def map[B](f: A => B): Monad[B] = flatMap{ v => Monad(f(v)) }
    def flatMap[B](f: A => Monad[B]): Monad[B] = f(value)
    def get(): A = value
  }

  def main(args: Array[String]): Unit = {
    val result = for {
      a <- Monad(1)
      b <- Monad(2)
      c <- Monad(3)
    } yield a + b + c
    println(result.get())

    val add = (int: Int) => Monad(int + 1)
    val multiply = (int: Int) => Monad(int * 2)
    println(Monad(1).flatMap(add).get() == add(1).get())
    println(Monad(1).flatMap(Monad(_)).get() == Monad(1).get())
    println(Monad(1).flatMap(add).flatMap(multiply).get() == add(1).flatMap(multiply).get())
    println(Monad(Monad(1)).flatMap { monad => monad }.get())
  }
}

Well, you actually did not implement THE Monad, but rather A Monad.
In particular, it seems you tried to implement something close to the IO Monad.

And hope not to sound rude, but this just means that you didn’t understand the idea at all; or that I misunderstood the question :stuck_out_tongue:
The good news is that you really don’t need to learn the Monad idea at all, and I would advise not focusing too much on it, especially at the beginning. Rather, learn how to use specific Monads like List, Option, Either, IO, etc.


Well, it depends exactly on what you want to do.
Again, this is not the Monad used to write very abstract code like the one in cats, for doing that you need to write a typeclass instead.
But, it also seems, that you actually didn’t want the Monad abstraction at all, but rather have a specific Monad, now the question is, which Monad do you want and why? Again, it seems you wanted to have something close to IO?

1 Like

Spelling that out a little more: Monad is essentially a pattern, not a specific data structure. Any data structure that follows those rules is a Monad. So List, Option, IO and so on are all Monads.

What Cats provides is essentially the reified version of that pattern, as a typeclass. If you can provide an implementation of that typeclass for a data structure, then poof, you have a fully-functional Monad, usable with all the functions that can work on a Monad (which are many).

So basically, you’ve provided one Monad (which, as @BalmungSan says, is more or less a simple version of the IO Monad, not getting into all the complex async and threading and stuff like that). Cats provides the abstraction of Monads, which can be applied to many data structures.

You might find it helpful to compare your version with the Cats version. Notice that yours takes just a plain data type A as the type parameter, whereas Cats takes an effect F[_]. That’s the big difference: Cats is providing a higher-order data type.

So for example, yours can be a Monad[String], which really isn’t “Monad”: it’s more accurate to call it IO[String] – an operation that can return a String. The Cats version could instead be, for example, Monad[List[String]] – a description of the rules that make List a Monad.

3 Likes

What was implemented here looks to me like something akin to the identity monad, rather than something akin to IO?

The by-value seems to indicate a desire for laziness, something I assume is related somehow to IO… but yeah, is still too weird.
It is actually closer to Eval, but I refrained to mention that one to avoid more confusion.

If you’re interesting in seeing how FP abstractions such as monad can be built up from nothing (rather than provided by a library like Cats), the book you want is Functional Programming in Scala by Pilquist, Bjarnason & Chiusano. There’s a Scala 2 edition and a Scala 3 edition. It’s considered something of a classic. It will walk you through how to define a Monad typeclass.

1 Like

Thanks, that’s the exact advice I am after! I have been using Scala for several years. List, Option, and Either are what I often apply in my program. Many articles I read mentioning on the internet about Monad; however, most of them show the usage of Cats; show simple examples; or just talk about math. Though it’s nice, the knowledge gleaned from those materials is fragment, and I find it’s difficult for me to connect the dot.

I want to learn by building the Monad (and other useful building blocks like IO as well), like what Cats offers. It doesn’t need to be exactly the same or that kind of robustness, but good enough that I can understand how to implement myself for the parts I need. The learning curve is steep, but recently I find the things I learned in the past start to make sense now (like interpreter pattern, applicative, and so on), though I understand it’s still far away from saying I understand those concepts well.

Thanks again for the advice, and suggestions!

1 Like

Thank you for the detail information. That one plus @BalmungSan’s reply answers many questions I have so far.

I attempted to check the code several years ago, but it’s very complicated to me. But it looks inevitably I have to look into Cats Monad. I will try again to see if I have better understanding.

Thank you very much!

Thank you for recommending the book. I will spend some time reading it.

Then the red book is exactly what you want :slight_smile:
(And the award for guessing the right answer goes to @SethTisue this time :stuck_out_tongue: :tada: )


Having said that, I would like to ask again, what is your motive for learning that?
As a person who wants to be a professor, I totally understand the joy of learning for the sake of learning, yet I also have seen a lot of folks who think they are learning the right thing whereas in practical terms they could be investing their time in more valuable things.

Thus, if your objective is how to use tools like cats, cats-effect or ZIO, and understand why many folks (like me) say those are the best tools to write concurrent heavy applications, I would recommend other resources.

1 Like

If you’re interesting in seeing how FP abstractions such as monad can be built up from nothing (rather than provided by a library like Cats), the book you want is Functional Programming in Scala by Pilquist, Bjarnason & Chiusano. There’s a Scala 2 edition and a Scala 3 edition.

Yes.

Here is a “perfectly respectable, precise, and terse definition” of a monad from the first edition:

That slide is from MonadFact #4.

Another book that does a great job of explaining monads is Functional Programming, Simplified (btw, there is a new edition in the making).

image

For example, I found it useful to learn about the Writer and State monads.

image

===========================================================

image

3 Likes

What was implemented here looks to me like something akin to the identity monad

Yes. The map and flatMap functions look like those of the identity monad.

Even though the identity monad does nothing, it has a meaning that gives us a partial answer to the question of what monads mean. Here is an excerpt from the 1st edition of Functional Programming in Scala:

Those slides are from Monad Fact #5

2 Likes

Before you study the IO monad, I (IMHO) would suggest studying some simple monads, e.g. Identity, Option and List.

----------------------------------------------------------------------------

----------------------------------------------------------------------------

Those slides are from Monad Fact #5

When you are ready, the red book (Functional Programming in Scala), literally walks you through the making of an IO monad.

That slide is from Game of Life - Polyglot FP - Haskell, Scala, Unison - Part 2

2 Likes

Thanks. I will check the book!

Partly because of work, the primary reason is just for fun. Also, the deeper understanding the FP, I find those concepts more or less help me avoid some traps when writing the code. A simple example is like passing a thunk instead of hard code with System.currentTimeMillis() in the program, though that still depends on scenarios.

Also, those concepts, even just scratching the surface, may help me reason something I do not expect in the future. For example, I read some ants colony papers; several years later, that helped me understand some trade offs in peer to peer design, thought it did not help me solve a million dollar problem.

Thank you for the slides! That identity monad slide answers a question I had when using sttp or slick (can’t remember which libs) where they make use of Id type for doing monadic operation.

1 Like