Skip to content

Instantly share code, notes, and snippets.

@johnynek
Last active June 4, 2020 23:47
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 johnynek/15c0b4a60e2b0a08e31c60717813dc7f to your computer and use it in GitHub Desktop.
Save johnynek/15c0b4a60e2b0a08e31c60717813dc7f to your computer and use it in GitHub Desktop.
A pattern for binding a typeclass to a value, but forgetting the container type in scala.
package WTC
import cats._
import cats.implicits._
abstract class WithTC[TC[_[_]], A] {
type F[_]
val value: F[A]
val typeClass: TC[F]
}
object WithTC {
final class Builder[TC[_[_]]] {
def apply[F1[_], A](fa: F1[A])(implicit tc: TC[F1]): WithTC[TC, A] =
new WithTC[TC, A] {
type F[x] = F1[x]
val value = fa
val typeClass = tc
}
}
def apply[TC[_[_]]]: Builder[TC] =
new Builder[TC]
// note, we don't know what the container is here,
def onFoldable(tc: WithTC[Foldable, Int]): List[Int] =
tc.typeClass.toList(tc.value)
onFoldable(WithTC[Foldable](Vector(1, 2, 3)))
onFoldable(WithTC[Foldable](List(1, 2, 3)))
// we can convert to List. We could even have a List[WithTC[Foldable, Int]]
def flatten(wcs: List[WithTC[Foldable, Int]]): List[Int] =
wcs.flatMap(onFoldable(_))
flatten(List(WithTC[Foldable](List(1, 2, 3)), WithTC[Foldable](Vector(4, 5, 6))))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment