sealed class TyEq() { abstract fun cast(a: A): B abstract fun rot(): TyEq class Refl() : TyEq() { override fun cast(a: A): A = a override fun rot(): TyEq = this } } sealed interface Expr { companion object { fun concat(x: Expr, y: Expr): Expr = Concat(TyEq.Refl(), x, y) fun string(s: String): Expr = Str(TyEq.Refl(), s) } data class Str( val ty: TyEq, val value: String, ) : Expr data class Concat( val ty: TyEq, val lhs: Expr, val rhs: Expr, ) : Expr } fun eval(e: Expr): T = when (e) { is Expr.Str -> e.ty.rot().cast(e.value) is Expr.Concat -> e.ty.rot().cast(eval(e.lhs) + eval(e.rhs)) } sealed class Nat> { fun succ(): S = S(this) abstract fun > finOf(ix: Nat): Fin? object Z : Nat() { override fun > finOf(ix: Nat): Fin? = null override fun toString(): String = "Z" } data class S>(val prev: Nat) : Nat>() { override fun > finOf(ix: Nat): Fin>? = when (ix) { Z -> Fin.Z() is S<*> -> when (val f = prev.finOf(ix.prev)) { null -> null else -> Fin.S(f) } } } } sealed class SomeNat { fun succ(): SomeNat = accept(object : Visitor { override fun > visit(nat: Nat): SomeNat = nat.succ().erase() }) abstract fun accept(visitor: Visitor): R companion object { val Z = Nat.Z.erase() fun > Nat.erase(): SomeNat = Wrap(this) } interface Visitor { fun > visit(nat: Nat): R } private data class Wrap>(val nat: Nat) : SomeNat() { override fun accept(visitor: Visitor): R = visitor.visit(nat) override fun toString(): String = "SomeNat(${nat})" } } sealed class Fin> { fun succ(): S = S(this) data class Z>(val unit: Unit = Unit) : Fin>() data class S>(val prev: Fin) : Fin>() } abstract class Vect> { abstract fun get(ix: Fin): A abstract val length: N data class Nil(val unit: Unit = Unit) : Vect() { override fun get(ix: Fin): A = when (ix) { else -> error("impossible") } override val length: Nat.Z = Nat.Z } data class Cons>(val head: A, val tail: Vect) : Vect>() { override fun get(ix: Fin>): A = when (ix) { is Fin.Z -> head is Fin.S -> tail.get(ix.prev) } override val length: Nat.S = tail.length.succ() } } fun main(args: Array) { println(eval(Expr.concat(Expr.string("hi"), Expr.string("world")))) println(Nat.Z.succ().succ().succ()) println(SomeNat.Z.succ().succ()) val xs = Vect.Cons(1, Vect.Cons(2, Vect.Nil())) println("xs=${xs}") println("length=${xs.length}") println(xs.get(Fin.Z())) println(xs.get(Fin.S(Fin.Z()))) println(Nat.Z.succ().succ().succ().finOf(Nat.Z)) println(Nat.Z.succ().succ().succ().finOf(Nat.Z.succ())) println(Nat.Z.succ().succ().succ().finOf(Nat.Z.succ().succ())) println(Nat.Z.succ().succ().succ().finOf(Nat.Z.succ().succ().succ())) println(Nat.Z.succ().succ().succ().finOf(Nat.Z.succ().succ().succ().succ())) }