Last active
September 23, 2017 04:41
-
-
Save logicalguess/4ea231302929651bc6e02bdef0ad876d to your computer and use it in GitHub Desktop.
unions and heterogeneous lists without shapeless
This file contains 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
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 | |
} | |
} | |
This file contains 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
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 | |
} | |
} | |
This file contains 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
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)) | |
} | |
} | |
This file contains 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
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