Dev Maha
Dev Maha

Reputation: 1143

Generics Issues while implementing monad

I saw the below code on SO. But the problem it has is that it's map and flatMap definitions aren't fully correct. map must be able to transform the inside value of a monadic container/context, and the same way a flatMap should take a value, transform it and put it back in the monadic context/container. In the example below it's taking an A and giving an A or M[A] (instead of A->B or A->M[B])

trait Mine[A] {
  def get(): A
  def map(f: A => A): Mine[A]
  def flatMap(f: A => Mine[A]): Mine[A]
}

case class Attempt1[A, B](a: (A, B)) extends Mine[(A, B)] {
  def get(): (A, B) = a
  def map(f: ((A, B)) => (A, B)): Mine[(A, B)] = {
   Attempt1(f(a._1, a._2))
  }
  def flatMap(f: ((A, B)) => Mine[(A, B)]): Mine[(A, B)] = {
   f(a._1, a._2)
  }
}

So I thought of changing it and that's where I got stuck. The below code is failing for all the right reasons but can someone guide on how to implement something similar?

trait Opt[A] {
 def map[B](f: A => B): Opt[B]
 def flatMap[B](f: A => Opt[B]): Opt[B]
}

case class Osome[A, B](a: (A, B)) extends Opt[(A, B)] {
 def flatMap[C, D](f: ((A, B)) => Opt[(C,D)]): Opt[(C, D)] = {
  f(a._1, a._2)
 }
 def map [C, D] (f: ((A, B)) => (C, D)): Opt[(C, D)] = {
  Osome(f(a._1, a._2))
 }

}

Upvotes: 0

Views: 123

Answers (1)

drexin
drexin

Reputation: 24403

The problem is, that you don't implement the map and flatMap methods of Opt in your Osome class, but you overload them. In your trait they both have one type parameter, but in your implementation they have two. Aside from that, your Osome would anyway not be a monad, as it restricts the resulting type of map and flatMap, where monads allow for arbitrary types.

Upvotes: 1

Related Questions