Created
December 3, 2011 15:44
-
-
Save szeiger/1427411 to your computer and use it in GitHub Desktop.
HLTest.scala
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 hltest | |
// Church Numerals | |
sealed trait Nat { | |
type Self <: Nat | |
type Apply[F[_], _] | |
type + [_ <: Nat] <: Nat | |
type * [_ <: Nat] <: Nat | |
type Flip_^ [_ <: Nat] <: Nat | |
type ^ [T <: Nat] = T # Flip_^[Self] | |
type ++ = Succ[Self] | |
def self: Self | |
def ++ = Nat.unsafe[++](value+1) | |
def + [T <: Nat](n: T): +[T] = Nat.unsafe[+[T]](value + n.value) | |
def * [T <: Nat](n: T): *[T] = Nat.unsafe[*[T]](value * n.value) | |
def ^ [T <: Nat](n: T): ^[T] = Nat.unsafe[^[T]](Math.pow(value, n.value).asInstanceOf[Int]) | |
def value: Int | |
override def toString = value.toString | |
type _0 = *[Nat._10] | |
type _1 = _0 # ++ | |
type _2 = _1 # ++ | |
type _3 = _2 # ++ | |
type _4 = _3 # ++ | |
type _5 = _4 # ++ | |
type _6 = _5 # ++ | |
type _7 = _6 # ++ | |
type _8 = _7 # ++ | |
type _9 = _8 # ++ | |
def _0 = this * Nat._10 | |
def _1 = _0 + Nat._1 | |
def _2 = _0 + Nat._2 | |
def _3 = _0 + Nat._3 | |
def _4 = _0 + Nat._4 | |
def _5 = _0 + Nat._5 | |
def _6 = _0 + Nat._6 | |
def _7 = _0 + Nat._7 | |
def _8 = _0 + Nat._8 | |
def _9 = _0 + Nat._9 | |
} | |
object Nat { | |
def unsafe[T <: Nat](value: Int) = | |
(if(value < cached.length) cached(value) else new Succ(value)).asInstanceOf[T] | |
type _0 = Zero.type | |
type _1 = _0 # ++ | |
type _2 = _1 # ++ | |
type _3 = _2 # ++ | |
type _4 = _3 # ++ | |
type _5 = _4 # ++ | |
type _6 = _5 # ++ | |
type _7 = _6 # ++ | |
type _8 = _7 # ++ | |
type _9 = _8 # ++ | |
type _10 = _9 # ++ | |
val _0: _0 = Zero | |
val _1 = new Succ(1).asInstanceOf[_1] | |
val _2 = new Succ(2).asInstanceOf[_2] | |
val _3 = new Succ(3).asInstanceOf[_3] | |
val _4 = new Succ(4).asInstanceOf[_4] | |
val _5 = new Succ(5).asInstanceOf[_5] | |
val _6 = new Succ(6).asInstanceOf[_6] | |
val _7 = new Succ(7).asInstanceOf[_7] | |
val _8 = new Succ(8).asInstanceOf[_8] | |
val _9 = new Succ(9).asInstanceOf[_9] | |
val _10 = new Succ(10).asInstanceOf[_10] | |
private[this] val cached = Array(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) | |
} | |
final object Zero extends Nat { | |
type Self = Zero.type | |
type Apply[F[_], X] = X | |
type + [X <: Nat] = X | |
type * [_ <: Nat] = Nat._0 | |
type Flip_^ [_ <: Nat] = Nat._1 | |
def self = this | |
def value = 0 | |
} | |
final class Succ[N <: Nat] private[hltest] (val value: Int) extends Nat { | |
type Self = Succ[N] | |
type -- = N | |
type Apply[F[_], X] = F[N#Apply[F, X]] | |
type + [X <: Nat] = Succ[N # + [X]] | |
type * [X <: Nat] = (N # * [X]) # + [X] | |
type Flip_^ [X <: Nat] = (N # Flip_^ [X]) # * [X] | |
def self = this | |
def -- : -- = Nat.unsafe[--](value-1) | |
} | |
// HList | |
trait HList { | |
type Self <: HList | |
type Tail <: HList | |
def self: Self | |
def :: [E](elem: E) = new HCons[E, Self](elem, self) | |
} | |
class HCons[H, T <: HList](val head: H, val tail: T) extends HList { | |
type Head = H | |
type Tail = T | |
type Self = HCons[H, T] | |
def self = this | |
} | |
object HNil extends HList { | |
type Self = HNil.type | |
type Tail = Nothing | |
def self = HNil | |
} | |
object HLTest extends App { | |
// Test the Church Numerals | |
{ | |
import Nat._; | |
println( (_2 + _2): _4 ) | |
println( (_3 + _0): _3 ) | |
println( (_0 + _2): _2 ) | |
println( (_1 + _2): _3 ) | |
println( (_2 * _3): _6 ) | |
println( (_2 ^ _3): _8 ) | |
println( (_3 ^ _2): _9 ) | |
println( _1._0: _10 ) | |
println( _1._6: (_8 # * [_2]) ) | |
val x: List[List[List[String]]] = (null: _3#Apply[List, String]) | |
} | |
// Test the HList | |
{ | |
val l1 = 42 :: "foo" :: 1.0 :: "bar" :: HNil | |
val l1a = l1.head | |
val l1b = l1.tail.head | |
val l1c = l1.tail.tail.head | |
val l1d = l1.tail.tail.tail.head | |
val x1 = null : l1.type#Tail#Tail#Tail | |
val x2 = null : Nat._3#Apply[({ type L[X <: HList] = X#Tail })#L, l1.type] | |
// ^^^^^ | |
//kinds of the type arguments ([X <: hltest.HList]X#Tail,l1.type) do not conform to the expected kinds of the type parameters (type F,type X). | |
// [X <: hltest.HList]X#Tail's type parameters do not match type F's expected parameters: | |
// type X's bounds >: Nothing <: hltest.HList are stricter than type _'s declared bounds >: Nothing <: Any | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment