Skip to content

Instantly share code, notes, and snippets.

@chrilves
Created November 23, 2018 16:31
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 chrilves/82014e9e335aa7a2cc13c5b864d9583a to your computer and use it in GitHub Desktop.
Save chrilves/82014e9e335aa7a2cc13c5b864d9583a to your computer and use it in GitHub Desktop.
A proof that the type `A` is of the form `F[elem]` for some type `elem`
/** A proof that the type {{{A}}} is of
* the form {{{F[elem]}}} for some type
* {{{elem}}}.
*/
sealed abstract class IsA[F[_], A] {
type elem
def fold[G[_]](p: G[F[elem]]): G[A]
@inline implicit final def to: A =:= F[elem] = {
type G[X] = X =:= F[elem]
fold[G](implicitly[F[elem] =:= F[elem]])
}
@inline implicit final def from: F[elem] =:= A = {
type G[X] = F[elem] =:= X
fold[G](implicitly[F[elem] =:= F[elem]])
}
}
object IsA {
final case class Proof[F[_], X]() extends IsA[F, F[X]] {
final type elem = X
@inline final def fold[G[_]](p: G[F[elem]]): G[F[X]] = p
}
@inline implicit def proof[F[_],elem]: IsA[F, F[elem]] =
Proof[F, elem]()
}
def length[A](a: A)(implicit proof: IsA[List, A]): Int = {
import proof._
a.length
}
def reverse[A](a: A)(implicit proof: IsA[List, A]): A = {
import proof._
a.reverse
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment