Skip to content

Instantly share code, notes, and snippets.

@johnynek
Forked from sritchie/test.scala
Last active December 12, 2015 12:39
Show Gist options
  • Save johnynek/4773840 to your computer and use it in GitHub Desktop.
Save johnynek/4773840 to your computer and use it in GitHub Desktop.
import annotation.implicitNotFound
@implicitNotFound(msg = "This message can never appear!")
trait ~>[A, B] { self =>
def apply(a: A): B
def invert(b: B): A = inverse.apply(b)
def inverse: B ~> A = new ~>[B,A] {
def apply(b: B) = self.invert(b)
override def invert(a: A) = self(a)
}
}
object ~> {
def connect[A,B](implicit prov: Provider[A,B]): A ~> B = prov.bij
}
sealed trait Provider[A,B] { def bij: A ~> B }
class Forward[A,B](override val bij: A ~> B) extends Provider[A,B]
class Reverse[A,B](invbij: B ~> A) extends Provider[A,B] { lazy val bij = invbij.inverse }
trait LowPriority {
implicit def reverse[A,B](implicit bij: B ~> A): Provider[A,B] = new Reverse(bij)
}
object Provider extends LowPriority {
implicit def forward[A,B](implicit bij: A ~> B): Provider[A,B] = new Forward(bij)
}
// Obviously not a bijection. Chill
implicit val toSBij = new ~>[Int,String] {
def apply(i: Int) = i.toString
override def invert(s: String) = s.toInt
}
/*
scala> ~>.connect[Int, String]
res7: ~>[Int,String] = $anon$1@4d90b2ca
scala> ~>.connect[String, Int]
res8: ~>[String,Int] = $tilde$greater$$anon$2@78dc17f
scala> ~>.connect[String, Double]
<console>:28: error: could not find implicit value for parameter prov: Provider[String,Double]
~>.connect[String, Double]
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment