#nullable enable using System; // --- interface Hk { } // --- static class Nat { public static Nat_Z Z() => new Nat_Z(); public static Nat_S S(this N prev) where N : Nat => new Nat_S(prev); public static Nat Narrow(this Hk hk) where N : Nat => (Nat)hk; public static TyEq, Nat_S> Succ(this TyEq ty) where N : Nat where M : Nat => new TyEq_Trust, Nat_S>(); public static TyEq Prev(this TyEq, Nat_S> ty) where N : Nat where M : Nat => new TyEq_Trust(); } // abstract record Nat() : Hk where N : Nat { public abstract R Accept(Nat_Visitor visitor); public abstract Fin? ToFin(uint value); public abstract TyEq? Equals(Nat other) where M : Nat; public abstract uint ToUInt(); } interface Nat_Mu { } // sealed record Nat_Z() : Nat { public override R Accept(Nat_Visitor visitor) => visitor.Visit(new TyEq_Refl(), this); public override Fin? ToFin(uint value) => null; public override TyEq? Equals(Nat other) => other.Accept?>(new Nat_Z_Equals_Visitor()); public override uint ToUInt() => 0; } sealed record Nat_Z_Equals_Visitor() : Nat_Visitor?, M> where M : Nat { TyEq? Nat_Visitor?, M>.Visit(TyEq ty, Nat_Z value) => ty.Rot(); TyEq? Nat_Visitor?, M>.Visit(TyEq> ty, Nat_S value) => null; } // interface Nat_S_Mu { } sealed record Nat_S(N Prev) : Nat>, Hk where N : Nat { public override R Accept(Nat_Visitor> visitor) => visitor.Visit(new TyEq_Refl>(), this); public override Fin>? ToFin(uint value) => value == 0 ? Fin.Z() : Prev.ToFin(value - 1)?.S(); public override TyEq, M>? Equals(Nat other) => other.Accept, M>?>(new Nat_S_Equals_Visitor(Prev)); public override uint ToUInt() => 1 + Prev.ToUInt(); } sealed record Nat_S_Equals_Visitor(N Prev) : Nat_Visitor, M>?, M> where N : Nat where M : Nat { TyEq, M>? Nat_Visitor, M>?, M>.Visit(TyEq ty, Nat_Z value) => null; TyEq, M>? Nat_Visitor, M>?, M>.Visit(TyEq> ty, Nat_S value) => Prev.Equals(value.Prev)?.Succ().Compose(ty.Rot()); } // interface Nat_Visitor where N : Nat { R Visit(TyEq ty, Nat_Z value); R Visit(TyEq> ty, Nat_S value) where M : Nat; } // --- static class Fin { public static Fin ToFin(this uint value, N bound) where N : Nat => bound.ToFin(value); public static Fin> Z() where N : Nat => new Fin_Z(); public static Fin> S(this Fin prev) where N : Nat => new Fin_S(prev); public static Fin Narrow(this Hk hk) where N : Nat => (Fin)hk; } // abstract record Fin() : Hk where N : Nat { public abstract R Accept(Fin_Visitor visitor); public A Impossible(TyEq ty) => throw new Exception("impossible: Fin"); } interface Fin_Mu { } // sealed record Fin_Z() : Fin> where N : Nat { public override R Accept(Fin_Visitor> visitor) => visitor.Visit(new TyEq_Refl>(), this); } // sealed record Fin_S(Fin Prev) : Fin> where N : Nat { public override R Accept(Fin_Visitor> visitor) => visitor.Visit(new TyEq_Refl>(), this); } // interface Fin_Visitor where N : Nat { R Visit(TyEq> ty, Fin_Z value) where M : Nat; R Visit(TyEq> ty, Fin_S value) where M : Nat; } // --- static class Vect { public static Vect Nil() => new Vect_Nil(); public static Vect> Cons(this Vect tail, A head) where N : Nat => new Vect_Cons(head, tail); public static A IndexOf(this Fin ix, Vect vect) where N : Nat => vect[ix]; } // abstract record Vect() where N : Nat { public abstract A this[Fin ix] { get; } public abstract N Length { get; } } // sealed record Vect_Nil() : Vect { public override A this[Fin ix] => ix.Impossible(new TyEq_Refl()); public override Nat_Z Length => Nat.Z(); } // sealed record Vect_Cons(A Head, Vect Tail) : Vect> where N : Nat { public override A this[Fin> ix] => ix.Accept(new Vect_Cons_Index_Visitor(this)); public override Nat_S Length => Tail.Length.S(); } sealed record Vect_Cons_Index_Visitor(Vect_Cons Cons) : Fin_Visitor> where N : Nat { public A Visit(TyEq, Nat_S> ty, Fin_Z value) where M : Nat => Cons.Head; public A Visit(TyEq, Nat_S> ty, Fin_S value) where M : Nat { var ix = ty.Prev().LiftL().Rot().Cast(value.Prev).Narrow(); return Cons.Tail[ix]; } } // --- abstract record TyEq() { public abstract B Cast(A a); public abstract TyEq Compose(TyEq ty); public abstract TyEq Rot(); public abstract TyEq, Hk> LiftL(); } sealed record TyEq_Refl() : TyEq { public override A Cast(A a) => a; public override TyEq Compose(TyEq ty) => ty; public override TyEq Rot() => this; public override TyEq, Hk> LiftL() => new TyEq_Refl>(); } sealed record TyEq_Trust() : TyEq { public override B Cast(A a) => (B)(object)a; public override TyEq Compose(TyEq ty) => new TyEq_Trust(); public override TyEq, Hk> LiftL() => new TyEq_Trust, Hk>(); public override TyEq Rot() => new TyEq_Trust(); } // --- interface SomeNat_Visitor { R Visit(N nat) where N : Nat; } interface SomeNat { R Accept(SomeNat_Visitor visitor); public static SomeNat Z() => Nat.Z().Erase(); } // static class SomeNat_Helpers { public static SomeNat ToSomeNat(this uint value) { SomeNat nat = SomeNat.Z(); for (uint i = 0; i < value; i++) { nat = nat.S(); } return nat; } public static SomeNat Erase(this N nat) where N : Nat => new SomeNat_Wrap(nat); public static SomeNat S(this SomeNat nat) => nat.Accept(new SomeNat_S_Visitor()); } sealed record SomeNat_S_Visitor() : SomeNat_Visitor { SomeNat SomeNat_Visitor.Visit(N nat) => nat.S().Erase(); } // sealed record SomeNat_Wrap(N Nat) : SomeNat where N : Nat { public R Accept(SomeNat_Visitor visitor) => visitor.Visit(Nat); } // --- public static class Program { public static void Main() { var xs = Vect.Nil().Cons(2).Cons(1); Console.WriteLine(xs[Fin.Z>()]); Console.WriteLine(xs[Fin.Z().S()]); Console.WriteLine(0u.ToFin(bound: xs.Length)?.IndexOf(xs)); Console.WriteLine(1u.ToFin(bound: xs.Length)?.IndexOf(xs)); Console.WriteLine(2u.ToFin(bound: xs.Length)?.IndexOf(xs).ToString() ?? "null"); Console.WriteLine(42u.ToSomeNat().Accept(new Example_SomeNat_Visitor())); Console.WriteLine(Nat.Z().S().S().S().Erase().Accept(new Example_SomeNat_Visitor())); } } sealed record Example_SomeNat_Visitor() : SomeNat_Visitor { uint SomeNat_Visitor.Visit(N nat) => nat.ToUInt(); }