Skip to content

Instantly share code, notes, and snippets.

@blouerat
Created May 13, 2015 18:15
Show Gist options
  • Save blouerat/b42180c847d9ad9899a4 to your computer and use it in GitHub Desktop.
Save blouerat/b42180c847d9ad9899a4 to your computer and use it in GitHub Desktop.
Inverse
trait HasInverse[A]
object HasInverse {
def apply[A]: HasInverse[A] = new HasInverse[A] {}
}
implicit def dummyHasInverse[A]: HasInverse[A] = HasInverse[A]
trait Inverse[A, B] { self =>
def value: A
def inverse: B
def swap: Inverse[B, A] = new Inverse[B, A] {
def value: B = self.inverse
def inverse: A = self.value
}
}
object Inverse {
def apply[A: HasInverse, B: HasInverse](a: A, b: B): Inverse[A, B] = new Inverse[A, B] {
def value = a
def inverse = b
}
}
implicit def swappedInverse[A, B](implicit i: Inverse[A, B]): Inverse[B, A] = i.swap
implicit def inverseHasInverse[A, B](implicit i: Inverse[A, B]): HasInverse[A] = HasInverse[A]
def inverse[A, B](a: A)(implicit i: Inverse[A, B]): B = i.inverse
implicit class InverseOps[A](a: A) {
def inverse[B](implicit i: Inverse[A, B]): B = i.inverse
}
@pavlosgi
Copy link

Hmmm... So would would happen if I had two Inverses of different kinds. ie apply(Left, Black) wouldn't this still work and give me an Inverse[Left, Black] which is invalid?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment