Skip to content

Instantly share code, notes, and snippets.

@lrytz
Created March 27, 2019 10:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lrytz/539040e992a09fcddab6e43138a00569 to your computer and use it in GitHub Desktop.
Save lrytz/539040e992a09fcddab6e43138a00569 to your computer and use it in GitHub Desktop.
import annotation.unchecked.uncheckedVariance
trait Bldr[-A, +To] { self =>
def result(): To
def mapResult[NTo](f: To => NTo): Bldr[A, NTo] = new Bldr[A, NTo] {
def result(): NTo = f(self.result())
}
}
trait ItFact[+CC[_]] {
def from[A](source: It[A]): CC[A]
def newBuilder[A]: Bldr[A, CC[A]]
}
/** CAUTION: only use this mixin when CC[A] =:= C */
trait DefaultFromSpecific[+A, +CC[_], +C] {
protected def fromSpecific(coll: It[A @uncheckedVariance]): C = iterableFactory.from(coll).asInstanceOf[C]
protected def newSpecificBuilder: Bldr[A @uncheckedVariance, C] = iterableFactory.newBuilder[A].mapResult(_.asInstanceOf[C])
def iterableFactory: ItFact[CC]
}
trait ItOps[+A, +CC[_], +C] {
def it: It[A]
protected def newSpecificBuilder: Bldr[A @uncheckedVariance, C]
protected def fromSpecific(coll: It[A @uncheckedVariance]): C
def iterableFactory: ItFact[CC]
def filter: C = fromSpecific(it)
def strictFilter: C = newSpecificBuilder.result()
def map[B](f: A => B): CC[B] = iterableFactory.newBuilder.result()
}
trait It[+A] extends ItOps[A, It, It[A]] with DefaultFromSpecific[A, It, It[A]] {
def it: It[A] = this
def iterableFactory: ItFact[It] = It
}
object It extends ItFact[It] {
def from[A](source: It[A]): It[A] = new It[A]{}
def newBuilder[A]: Bldr[A,It[A]] = new Bldr[A, It[A]] { def result(): It[A] = new It[A]{} }
}
trait SqOps[A, +CC[_], +C] extends ItOps[A, CC, C]
trait Sq[A] extends It[A] with SqOps[A, Sq, Sq[A]] with DefaultFromSpecific[A, Sq, Sq[A]] {
override def iterableFactory: ItFact[Sq] = Sq
def flup = 0
}
object Sq extends ItFact[Sq] {
def from[A](source: It[A]): Sq[A] = new Sq[A]{}
def newBuilder[A]: Bldr[A, Sq[A]] = new Bldr[A, Sq[A]] { def result(): Sq[A] = new Sq[A]{} }
}
trait Acc[A, +CC[X] <: Sq[X], +C <: Sq[A]] extends Sq[A] with SqOps[A, CC, C] {
protected def fromSpecificImpl(coll: It[A]): C
protected def newSpecificBuilderImpl: Bldr[A, C]
protected def iterableFactoryImpl: ItFact[CC]
protected override def fromSpecific(coll: It[A]): C = fromSpecificImpl(coll)
protected override def newSpecificBuilder: Bldr[A, C] = newSpecificBuilderImpl
override def iterableFactory: ItFact[CC] = iterableFactoryImpl
}
trait AnyAcc[A] extends Acc[A, AnyAcc, AnyAcc[A]] {
protected override def fromSpecificImpl(coll: It[A]): AnyAcc[A] = iterableFactory.from(coll)
protected override def newSpecificBuilderImpl: Bldr[A, AnyAcc[A]] = iterableFactory.newBuilder
override def iterableFactoryImpl: ItFact[AnyAcc] = AnyAcc
def flap = 1
}
object AnyAcc extends ItFact[AnyAcc] {
def from[A](source: It[A]): AnyAcc[A] = new AnyAcc[A] {}
def newBuilder[A]: Bldr[A, AnyAcc[A]] = new Bldr[A, AnyAcc[A]] { def result(): AnyAcc[A] = new AnyAcc[A]{} }
}
trait IntAcc extends Acc[Int, AnyAcc, IntAcc] {
protected override def fromSpecificImpl(coll: It[Int]): IntAcc = new IntAcc{}
protected override def newSpecificBuilderImpl: Bldr[Int, IntAcc] = new Bldr[Int, IntAcc] { def result(): IntAcc = new IntAcc{} }
override def iterableFactoryImpl: ItFact[AnyAcc] = AnyAcc
}
object Test {
def main(args: Array[String]): Unit = {
val sq = new Sq[String] { }
println(sq.filter.flup)
val ia = new IntAcc{}
println(((ia.filter: IntAcc).map(_ => ""): AnyAcc[String]).flap)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment