Skip to content

Instantly share code, notes, and snippets.

@logicalguess
Last active September 23, 2017 04:41
Show Gist options
  • Save logicalguess/4ea231302929651bc6e02bdef0ad876d to your computer and use it in GitHub Desktop.
Save logicalguess/4ea231302929651bc6e02bdef0ad876d to your computer and use it in GitHub Desktop.
unions and heterogeneous lists without shapeless
package logicalguess.union
import scala.reflect.runtime.universe._
trait DepTyped {
type U <: Union
val tu: Typed[U]
def add[In : TypeTag](in: In)= new DepTyped {
override type U = DepTyped.this.U | In
override val tu: Typed[U] = DepTyped.this.tu.add(in)
}
def values = tu.values
def contains[In](in: In)(implicit ev: isPartOf[In, U]) = tu.contains(in)
def getType = tu.getType
}
object DepTyped {
def empty = new DepTyped {
type U = Nothing
override val tu: Typed[Nothing] = Typed.empty
}
}
object DepTypedTest {
def main(args: Array[String]): Unit = {
val c = DepTyped.empty.add(1).add("a").add("b").add(2)
println(c.getType)
//Nothing | Int | java.lang.String | java.lang.String | Int
println(c.values)
//List(1, a, b, 2)
println(c.contains(7))
//false
println(c.contains("a"))
//true
// println(c.contains(2.0))
// Error:(30, 26) diverging implicit expansion for type logicalguess.union.isPartOf[Double,U]
// starting with method rightPart in object isPartOf
}
}
package logicalguess.union
trait HTyped {
type U <: Union
val values: List[Any]
def add[In](in: In) = new HTyped {
override type U = In | HTyped.this.U
override val values = HTyped.this.values :+ in
}
def contains[In](in: In)(implicit ev: isPartOf[In, U]) = values.contains(in)
}
object HTyped {
def empty = new HTyped {
override type U = Nothing
override val values = Nil
}
}
object HTypedTest {
def main(args: Array[String]): Unit = {
val c = HTyped.empty.add(1).add("a").add("b").add(2)
println(c.values)
//List(2, b, a, 1)
println(c.contains(7))
//false
println(c.contains("a"))
//true
// println(c.contains(1.0))
// Error:(37, 23) diverging implicit expansion for type logicalguess.union.isPartOf[Double,U]
// starting with method rightPart in object isPartOf
}
}
package logicalguess.union
import scala.reflect.runtime.universe._
case class Typed[U <: Union: TypeTag](values: List[Any]) {
def add[In : TypeTag](in: In) = Typed[U | In](values :+ in)
def contains[In](in: In)(implicit ev: isPartOf[In, U]) = values.contains(in)
def getType = typeTag[U].tpe
}
object Typed {
def empty = Typed[Nothing](Nil)
}
object TypedTest {
def main(args: Array[String]): Unit = {
val t: Typed[Nothing | Int | String | String | Int] = Typed.empty.add(1).add("a").add("b").add(2)
println(t.contains(7))
// false
println(t.getType)
// Nothing | Int | java.lang.String | java.lang.String | Int
println(t)
// Typed(List(1, a, b, 2))
}
}
package logicalguess.union
/**
* http://blog.knutwalker.de/typed-actors/tut/union.html
*/
import scala.annotation.implicitNotFound
sealed trait Union
sealed trait |[+A, +B] extends Union
@implicitNotFound("Cannot prove that ${A} is a union type.")
sealed trait IsUnion[-A] {
type Out <: Union
}
object IsUnion {
type Aux[-A0, U0 <: Union] = IsUnion[A0] {type Out = U0}
implicit def isUnion[A <: Union]: Aux[A, A] =
new IsUnion[A] {
type Out = A
}
}
@implicitNotFound("Cannot prove that message of type ${A} is a member of ${U}.")
sealed trait isPartOf[A, +U <: Union]
object isPartOf extends IsPartOf0 {
implicit def leftPart[A](implicit ev: A isNotA Union): isPartOf[A, A | Nothing] =
null
implicit def rightPart[A](implicit ev: A isNotA Union): isPartOf[A, Nothing | A] =
null
}
sealed trait IsPartOf0 {
implicit def tailPart1[A, U <: Union](implicit partOfTl: A isPartOf U): isPartOf[A, U | Nothing] =
null
implicit def tailPart2[A, U <: Union](implicit partOfTl: A isPartOf U): isPartOf[A, Nothing | U] =
null
}
// @annotation.implicitAmbiguous("${A} must not be <: ${B}")
sealed trait isNotA[A, B]
object isNotA {
implicit def nsub[A, B]: A isNotA B = null
// $COVERAGE-OFF$Code only exists to prove non-equality and is expected to never execute
implicit def nsubAmbig1[A, B >: A]: A isNotA B = sys.error("Unexpected invocation")
implicit def nsubAmbig2[A, B >: A]: A isNotA B = sys.error("Unexpected invocation")
// $COVERAGE-ON$
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment