Created
January 17, 2016 13:43
-
-
Save kmizu/339dd78052c68914a412 to your computer and use it in GitHub Desktop.
Emulate Generics using Abstract Type Members
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
trait List {self => | |
type E | |
def head: self.E | |
def tail: List { type E = self.E } | |
} | |
trait Cons extends List {self => | |
val head: E | |
val tail: List { type E = self.E } | |
} | |
trait Nil extends List {self => | |
def head: E = sys.error("no such element") | |
def tail: List { type E = self.E } = sys.error("empty list") | |
} | |
trait Function { | |
type In | |
type Out | |
def apply(arg: In): Out | |
} | |
trait Mapper { | |
type A | |
type B | |
def map(list: List { type E = A })(fun: Function { type In = A; type Out = B }): List { type E = B } = list match { | |
case x: Cons => | |
new Cons { | |
type E = B | |
val head = fun.apply(x.head) | |
val tail = map(x.tail)(fun) | |
} | |
case x: Nil => | |
new Nil { | |
type E = B | |
} | |
} | |
} | |
trait ForEach { | |
type A | |
def foreach(list: List { type E = A })(fun: Function { type In = A; type Out = Unit }): Unit = list match { | |
case x: Cons => | |
fun.apply(x.head) | |
foreach(x.tail)(fun) | |
case x: Nil => | |
() | |
} | |
} | |
object Main { | |
def main(args: Array[String]): Unit = { | |
val list = new Cons { | |
type E = Int | |
val head = 1 | |
val tail = new Cons { | |
type E = Int | |
val head: E = 2 | |
val tail = new Cons { | |
type E = Int | |
val head = 3 | |
val tail = new Nil { type E = Int } | |
} | |
} | |
} | |
val newList = new Mapper { | |
type A = Int | |
type B = Int | |
}.map(list)(new Function { | |
type In = Int | |
type Out = Int | |
def apply(arg: In): Out = arg + 1 | |
}) | |
new ForEach { | |
type A = Int | |
}.foreach(newList)(new Function { | |
type In = Int | |
type Out = Unit | |
def apply(arg: In): Out = println(arg) | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment