Skip to content

Instantly share code, notes, and snippets.

@bishabosha
Created November 15, 2021 16:00
Show Gist options
  • Save bishabosha/c45e90b7fe9765ea5ebe666cd4ae2fb4 to your computer and use it in GitHub Desktop.
Save bishabosha/c45e90b7fe9765ea5ebe666cd4ae2fb4 to your computer and use it in GitHub Desktop.
demonstration that the cats style of type class definition and syntax does not play well with type inference
// using scala 3.1.0
package mycats:
trait Semigroup[A]:
def combine(a1: A, a2: A): A
class SemigroupOps[A](a1: A)(implicit ev: Semigroup[A]):
def combine(a2: A): A = ev.combine(a1, a2)
implicit def mkSemigroupOps[A](a: A)(implicit ev: Semigroup[A]): SemigroupOps[A] = new SemigroupOps[A](a)
enum Maybe[+A]:
case Just(a: A)
case Nothing
given [A: Semigroup]: Semigroup[Maybe[A]] with
def combine(a1: Maybe[A], a2: Maybe[A]): Maybe[A] =
a1 match
case Maybe.Nothing => Maybe.Nothing
case Maybe.Just(x) =>
a2 match
case Maybe.Nothing => Maybe.Nothing
case Maybe.Just(y) => Maybe.Just(x combine y)
given [A: Semigroup]: Semigroup[Option[A]] with
def combine(a1: Option[A], a2: Option[A]): Option[A] =
a1 match
case None => None
case Some(x) =>
a2 match
case None => None
case Some(y) => Some(x combine y)
given Semigroup[Int] with
def combine(a1: Int, a2: Int): Int =
a1 + a2
package example:
import mycats.Maybe
import mycats.{Semigroup, given}
@main def Main =
// no TC is found for these narrow examples
println(Maybe.Just(1) combine Maybe.Just(2))
println(Some(1) combine Some(2))
println(Option(1) combine Option(2)) // compiles
println(summon[Semigroup[Option[Int]]]) // compiles
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment