Skip to content

Instantly share code, notes, and snippets.

@tschuchortdev
Last active September 5, 2023 11:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tschuchortdev/4b5d5e867451c7b4b10458cba47dba51 to your computer and use it in GitHub Desktop.
Save tschuchortdev/4b5d5e867451c7b4b10458cba47dba51 to your computer and use it in GitHub Desktop.
Scala 2 existential typeclass pattern
object Main {
def main(args: Array[String]) = {
implicit val showInt = new Show[Int] {
override def show(a: Int): String = a.toString
}
implicit val readInt = new Read[Int] {
override def read(s: String): Int = s.toInt
}
val a = 5
val e = Exists[Show](a)
e match {
case Exists(value, tc) => println(tc.show(value))
}
}
}
trait Show[A] {
def show(a: A): String
}
trait Read[A] {
def read(s: String): A
}
sealed trait Exists[C[_]] {
type Value
val value: Value
val typeClassInstance: C[Value]
final def use[R](f: C[Value] => Value => R): R = f(typeClassInstance)(value)
}
object Exists {
private class ExistsConcrete[A, C[_]](override val value: A, override val typeClassInstance: C[A]) extends Exists[C] {
override type Value = A
}
def apply[C[_]]: ApplyPartialApplicationHelper1[C] = new ApplyPartialApplicationHelper1()
class ApplyPartialApplicationHelper1[C[_]] private[Exists] {
def apply[A](a: A)(implicit tc: C[A]): Exists[C] = new ExistsConcrete[A, C](a, tc)
}
def unapply[C[_]](e: Exists[C]): Some[(e.Value, C[e.Value])] = Some(e.value, e.typeClassInstance)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment