Created
February 20, 2015 20:42
-
-
Save drdozer/e01cdcd5c856d33378dc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import simulacrum._ | |
import scala.annotation.implicitNotFound | |
@implicitNotFound("Could not find constructor for ${T} that takes a single argument of ${A}") | |
trait Constructor1[+T, -A] { | |
def apply(a: A): T | |
} | |
@implicitNotFound("Could not find destructor for ${T} that decomposes into a single argument of ${A}") | |
trait Destructor1[-T, +A] { | |
def unapply(t: T): Option[A] | |
} | |
trait Companion1[T, A] extends Constructor1[T, A] with Destructor1[T, A] { | |
def apply(a: A): T | |
def unapply(t: T): Option[A] | |
} | |
trait Companion2[T, A, B] { | |
def apply(a: A, b: B): T | |
def unapply(t: T): Option[(A, B)] | |
} | |
trait Companion3[T, A, B, C] { | |
def apply(a: A, b: B, c: C): T | |
def unapply(t: T): Option[(A, B, C)] | |
} | |
trait Companion4[T, A, B, C, D] { | |
def apply(a: A, b: B, c: C, d: D): T | |
def unapply(t: T): Option[(A, B, C, D)] | |
} | |
@typeclass trait Companion_*[T[_]] { | |
def apply[A](as: A*): T[A] | |
def unapply[A](ta: T[A]): Option[Seq[A]] | |
} | |
@implicitNotFound("Could not find hint for constructing ${A} -> ${B} -> ${C}") | |
trait ConstructorHint[A, B, C] | |
trait Cstr[α] { | |
type λ[β] = ConstructorChain[β, α] | |
} | |
@implicitNotFound("Could not build a constructor chain from ${S} to ${T}") | |
trait ConstructorChain[-S, +T] extends Function1[S, T] { | |
def apply(s: S): T | |
} | |
object ConstructorChain extends ConstructorChain1 { | |
implicit def fromCast[S, T](implicit ev: S <:< T): ConstructorChain[S, T] = new ConstructorChain[S, T] { | |
override def apply(a: S): T = a | |
} | |
} | |
trait ConstructorChain1 extends ConstructorChain2 { | |
implicit def fromConstructor1[S, T](implicit | |
c1: Constructor1[T, S]): ConstructorChain[S, T] = new ConstructorChain[S, T] { | |
override def apply(a: S): T = c1.apply(a) | |
} | |
} | |
trait ConstructorChain2 { | |
implicit def chain[R, S, T](implicit | |
ch: ConstructorHint[R, S, T], | |
bt: ConstructorChain[S, T], | |
ab: ConstructorChain[R, S]): ConstructorChain[R, T] = new ConstructorChain[R, T] { | |
override def apply(r: R) = bt.apply(ab.apply(r)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment