I am having issues with cats
/monads
/understanding.
Please consider following snippet:
import cats._
import cats.implicits._
final case class My[T]()
implicit val monadMy: Monad[My] = new Monad[My] { ... }
// this compiles
def test11[A, B](m: My[A], f: A => B): My[B] = m.map(f)
// this fails: value map is not a member of My[Nothing]
def test12[B](m: My[Nothing], f: Nothing => B): My[B] = m.map(f)
// this compiles
def test21[A, B](m: My[A], f: A => My[B]): My[B] = m.flatMap(f)
// this fails: type mismatch;
// [error] found : A => My[Nothing]
// [error] required: A => My[B]
def test22[A](m: My[A], f: A => My[Nothing]): My[Nothing] = m.flatMap(f)
I realize that test12
may look strange however it would allow for
syntax:
for (...; nothing <- My[Nothing]()) yield nothing
But failure shown in test22
makes cats.monad
unusable for my case.
Is monad of Nothing
violates monad laws?
Please assist, I would want to be able to flatMap
M[Nothing]
.
Thanks in advance.
UPDATE This minimal code snippet would compile if I made My
covariant, but unfortunately originally I use cats.Free
, which I don't have access to.
UPDATE One more workaround is to use polymorphic function everywhere I use Nothing
, i.e. use test11
everywhere I need test12
, but again, I would like to understand why behavior for M[Nothing]
is different than for any other type.
UPDATE BTW, if I change Nothing
to e.g. Int
it will compile. So, looks like this is by design. But why?
UPDATE Another workaround: switch to scalaz
.
UPDATE Looks like issue is related purely to scala
.
UPDATE Workaround: declare undefined type Bottom <: Nothing
and use it instead.