better-monadic-for icon indicating copy to clipboard operation
better-monadic-for copied to clipboard

Alternative `flatMap` possible?

Open alexandru opened this issue 5 years ago • 1 comments

Scala's "for comprehensions" first try to use withFilter and then fallback to filter if it doesn't exist.

I wonder if in a compiler plugin like this we could do the same thing for flatMap ... try a different a different name first, like flatMapT or something and if the type doesn't have it, then fallback to flatMap.


My problem is basically described here: https://contributors.scala-lang.org/t/proposal-for-opaque-type-aliases/2947/139

TL;DR — the flatMap on EitherT is:

// Does left widening
def flatMap[AA >: A, D](f: B => EitherT[F, AA, D])(implicit F: Monad[F]): EitherT[F, AA, D]

Which is basically different than the flatMap we get by implementing cats.FlatMap:

// No type widening
def flatMap[D](f: B => EitherT[F, A, D])(implicit F: Monad[F]): EitherT[F, A, D]

And if EitherT has an "opaque type" encoding, then these 2 signatures end up being in conflict and an explicit import cats.implicits._ will mask the first definition.

And giving that function a different name isn't a problem, we've got IDEs that help with the auto-completion, but in such a case the problem will be the for comprehensions, which in FP heavy code are ubiquitous.

alexandru avatar Feb 03 '20 22:02 alexandru

@alexandru Scala doesn't fallback to filter anymore:

I guess you could try to do what the PR did in reverse, kind of, but I'm actually not familiar with that machinery at all.

Alternatively, you can ditch cats.implicits._ in your project and have your own syntax object:

object appImplicits extends cats.syntax.AllSyntax /* with a ton of other traits */ {
  implicit def opsForEitherT[F, E, A](self: MyEitherT[F, E, A]): MyEitherT.Ops[F, E, A] = ???
}

this should work because your ops will take priority over inherited cats' ones.

oleg-py avatar Feb 04 '20 06:02 oleg-py