Last active
October 6, 2015 20:48
-
-
Save rklaehn/0f9271b2fc6ceeae699a to your computer and use it in GitHub Desktop.
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
// -Yno-predef | |
package collection | |
import scala.Predef.{???, println, implicitly} | |
trait Foreachable[T, U] { | |
def foreach(value: T, f: U ⇒ Any): Unit | |
} | |
trait Indexable[T, U] { | |
def apply(value: T, index: Int): U | |
} | |
trait Sized[T] { | |
def size(value: T): Long | |
} | |
trait Headed[T, U] { | |
def head(value: T): U | |
} | |
trait Tailed[T] { | |
def tail(value: T): T | |
} | |
trait ConsUnapply[T, U] { | |
def unapply(x: T): Option[(U, T)] | |
} | |
object syntax { | |
implicit class IndexableOps[T, U](value: T)(implicit ev: Indexable[T, U]) { | |
def apply(index: Int): U = ev.apply(value, index) | |
} | |
implicit class SizedOps[T: Sized](value: T) { | |
def xSize: Long = implicitly[Sized[T]].size(value) | |
} | |
implicit class HeadedOps[T, U](value: T)(implicit ev: Headed[T, U]) { | |
def xHead: U = ev.head(value) | |
} | |
implicit class TailedOps[T: Tailed](value: T) { | |
def xTail: T = implicitly[Tailed[T]].tail(value) | |
} | |
implicit class ForeachableOps[T, U](value: T)(implicit ev: Foreachable[T, U]) { | |
def foreach(f: U ⇒ Any): Unit = ev.foreach(value, f) | |
} | |
} | |
object StreamInstances { | |
trait HasSize { | |
implicit def streamHasSize[T]: Sized[Stream[T]] = new Sized[Stream[T]] { | |
override def size(value: Stream[T]): Long = value.size | |
} | |
} | |
trait HasHead { | |
implicit def streamHasHead[T]: Headed[Stream[T], T] = new Headed[Stream[T], T] { | |
override def head(value: Stream[T]): T = value.head | |
} | |
} | |
trait HasTail { | |
implicit def streamHasTail[T]: Tailed[Stream[T]] = new Tailed[Stream[T]] { | |
override def tail(value: Stream[T]): Stream[T] = value.tail | |
} | |
} | |
} | |
object ArrayInstances { | |
trait HasForeach { | |
implicit def arrayHasForeachable[T]: Foreachable[Array[T], T] = new Foreachable[Array[T], T] { | |
import scala.Predef._ | |
override def foreach(value: Array[T], f: (T) ⇒ Any): Unit = value.foreach(f) | |
} | |
} | |
trait HasIndexable { | |
implicit def arrayHasIndexable[T]: Indexable[Array[T], T] = new Indexable[Array[T], T] { | |
override def apply(value: Array[T], index: Int): T = value.apply(index) | |
} | |
} | |
trait HasSize { | |
implicit def arrayHasSize[T]: Sized[Array[T]] = new Sized[Array[T]] { | |
override def size(value: Array[T]): Long = value.length | |
} | |
} | |
trait HasHead { | |
implicit def arrayHasHead[T]: Headed[Array[T], T] = new Headed[Array[T], T] { | |
import scala.Predef._ | |
override def head(value: Array[T]): T = value.head | |
} | |
} | |
trait HasTail { | |
implicit def arrayHasTail[T]: Tailed[Array[T]] = new Tailed[Array[T]] { | |
import scala.Predef._ | |
override def tail(value: Array[T]): Array[T] = value.tail | |
} | |
} | |
trait HasConsUnapply { | |
implicit def arrayHasConsUnapply[T]: ConsUnapply[Array[T], T] = new ConsUnapply[Array[T], T] { | |
import scala.Predef._ | |
override def unapply(x: Array[T]): Option[(T, Array[T])] = if(x.isEmpty) None else Some((x.head, x.tail)) | |
} | |
} | |
} | |
object ListInstances { | |
private class ListTc[T] extends Sized[List[T]] with Headed[List[T], T] with Tailed[List[T]] { | |
override def size(value: List[T]): Long = value.size | |
override def head(value: List[T]): T = value.head | |
override def tail(value: List[T]): List[T] = value.tail | |
} | |
trait HasSize { | |
implicit def listHasSize[T]: Sized[List[T]] = new ListTc[T] | |
} | |
trait HasHead { | |
implicit def listHasHead[T]: Headed[List[T], T] = new ListTc[T] | |
} | |
trait HasTail { | |
implicit def listHasTail[T]: Tailed[List[T]] = new ListTc[T] | |
} | |
} | |
object ops { | |
trait `O(1)` extends ArrayInstances.HasSize | |
object `O(1)` extends `O(1)` | |
trait `O(N)` | |
extends `O(1)` | |
with ListInstances.HasSize | |
with ArrayInstances.HasForeach | |
with ArrayInstances.HasConsUnapply | |
object `O(N)` extends `O(N)` | |
trait NonTerminating extends `O(N)` with StreamInstances.HasSize | |
object NonTerminating extends NonTerminating | |
trait Partial | |
extends `O(N)` | |
with ArrayInstances.HasHead | |
with ArrayInstances.HasTail | |
with ListInstances.HasHead | |
with ListInstances.HasTail | |
with StreamInstances.HasHead | |
with StreamInstances.HasTail | |
with ArrayInstances.HasIndexable | |
object Partial extends Partial | |
trait All extends NonTerminating with Partial | |
object All extends All | |
} | |
object ::: { | |
def unapply[T, U](x: T)(implicit ev: ConsUnapply[T, U]): Option[(U, T)] = | |
ev.unapply(x) | |
} | |
object NNil { | |
def unapply[T](x: T)(implicit ev: Sized[T]): Boolean = ev.size(x) == 0 | |
} | |
object Test { | |
import syntax._ | |
import ops.`O(1)`._ | |
Array(1,2,3).xSize | |
// List(1,2,3).xSize // does not compile | |
// Stream(1,2,3).xSize // does not compile | |
import ops.`O(N)`._ | |
List(1,2,3).xSize // does compile due to the O(n) import | |
import ops.NonTerminating._ | |
Stream(1,2,3).xSize // does compile due to the NonTerminating import | |
import ops.Partial._ | |
Array(1,2,3).xHead | |
List(1, 2, 3).xHead | |
Stream(1,2,3).xHead | |
Array(1,2,3).xTail | |
List(1, 2, 3).xTail | |
Stream(1,2,3).xTail | |
} | |
object Test2 extends App { | |
import syntax._ | |
import ops.All._ | |
Array(1,2,3) match { | |
case x ::: y ⇒ println(s"$x $y") | |
case NNil() ⇒ println(s"Nope") | |
} | |
Array.empty[Int] match { | |
case x ::: y ⇒ println(s"$x $y") | |
case NNil() ⇒ println(s"Nope") | |
} | |
for(x ← Array(1,2,3)) | |
println(x) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment