i studying code example type level programming in scala:
object typelevel { sealed trait true extends bool { type if[t <: up, f <: up, up] = t } sealed trait false extends bool { type if[t <: up, f <: up, up] = f } sealed trait bool { type if[t <: up, f <: up, up] <: } object bool { type &&[a <: bool, b <: bool] = a#if[b, false, bool] type ||[a <: bool, b <: bool] = a#if[true, b, bool] type not[a <: bool] = a#if[false, true, bool] } case class boolrep[b <: bool](val value: boolean) def toboolean[b <: bool](implicit b: boolrep[b]) = b.value implicit val falserep: boolrep[false] = boolrep[false](false) implicit val truerep: boolrep[true] = boolrep[true](true) sealed trait comparison { type match[iflt <: up, ifeq <: up, ifgt <: up, up] <: type gt = match[false, false, true, bool] type lt = match[true, false, false, bool] type eq = match[false, true, false, bool] type le = match[true, true, false, bool] type ge = match[false, true, true, bool] } sealed trait gt extends comparison { type match[iflt <: up, ifeq <: up, ifgt <: up, up] = ifgt } sealed trait lt extends comparison { type match[iflt <: up, ifeq <: up, ifgt <: up, up] = iflt } sealed trait eq extends comparison { type match[iflt <: up, ifeq <: up, ifgt <: up, up] = ifeq } sealed trait nat { type match[nonzero[n <: nat] <: up, ifzero <: up, up] <: type compare[n <: nat] <: comparison } sealed trait _0 extends nat { type match[nonzero[n <: nat] <: up, ifzero <: up, up] = ifzero type compare[n <: nat] = n#match[constlt, eq, comparison] type constlt[a] = lt } sealed trait succ[n <: nat] extends nat { type match[nonzero[n <: nat] <: up, ifzero <: up, up] = nonzero[n] type compare[o <: nat] = o#match[n#compare, gt, comparison] } type _1 = succ[_0] type _2 = succ[_1] type _3 = succ[_2] type _4 = succ[_1] type is0[a <: nat] = a#match[constfalse, true, bool] type constfalse[a] = false type consttrue[a] = true def printall(strings: string*): unit = { println(strings.mkstring("\n")) } def main(args: array[string]) { import bool.{&&, ||, not} printall( toboolean[true && false || not[false]].tostring, toboolean[is0[_0]].tostring, toboolean[_0#compare[_0]#eq].tostring, toboolean[_1#compare[_0]#gt] tostring, toboolean[_0#compare[_1]#lt] tostring, toboolean[_1#compare[_2]#lt] tostring ) } }
this allows compare natural numbers @ compile time. can trace how _1#compare[_2]#lt
works:
succ[_0]#compare[_2]#lt
_2#match[_0#compare, gt, comparison]#lt
here lost. signature of compare
in _0
type compare[n <: nat] = n#match[constlt, eq, comparison]
so needs 1 parameter, , definition of type relies on parameter n
. _0#compare
doesn't make sense. explain how works here?
i figured out:
→ _1#compare[_2]#lt
→ succ[_0]#compare[_2]#lt
→ _2#match[_0#compare, gt, comparison]#lt
→ succ[_1]#match[_0#compare[_1], gt, comparison]#lt
……… _1
in _0#compare[_1]
inferred.
→ _0#compare[_1]#lt
→ lt#lt
→ true
Comments
Post a Comment