Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
9707a3f
disjunctive subtyping
auht Feb 25, 2025
cc87059
Changes from meeting
LPTK Feb 26, 2025
0298463
disjoint upperbound
auht Mar 5, 2025
bf4c763
Merge remote-tracking branch 'upstream/hkmc2' into logic-subtyping
auht Mar 5, 2025
ec5c55e
no disjoint upperbound
auht Mar 5, 2025
aa956a7
multiple disjointness
auht Mar 5, 2025
8bad1a5
Changes from meeting
LPTK Mar 6, 2025
86d300d
Add test case and move tests to logicsub folder
LPTK Mar 6, 2025
3b34199
constraints solving nested disjsub
auht Mar 7, 2025
ae28b42
ues linkedhashset
auht Mar 10, 2025
2f1f5f3
traverse disjsub
auht Mar 12, 2025
3d383a2
Changes from meeting
LPTK Mar 13, 2025
00e397b
fix pretty printer type traverse and tv subst
auht Mar 13, 2025
bdd4b7a
Merge remote-tracking branch 'upstream/hkmc2' into logic-subtyping
auht Mar 13, 2025
0bbfeca
wip rcdtype implementation
auht Mar 20, 2025
3a67c1f
wip rcdtype implementation and fun args disjointness
auht Mar 22, 2025
bd53f6f
intersections wf check
auht Mar 24, 2025
92dc44a
fix nested record wf check
auht Mar 26, 2025
69bcc5a
wip refined if
auht Mar 28, 2025
081de12
Update hkmc2/shared/src/test/mlscript/logicsub/Records.mls
auht Mar 28, 2025
52c6941
Merge remote-tracking branch 'upstream/hkmc2' into logic-subtyping
auht Mar 28, 2025
55b9066
wip fix
auht Apr 2, 2025
d99f3af
wip else branch disjointness
auht Apr 4, 2025
93d7ff6
fix if disjsub
auht Apr 6, 2025
3cd0f96
wip if
auht Apr 8, 2025
4996431
Merge remote-tracking branch 'upstream/hkmc2' into logic-subtyping
auht Apr 8, 2025
3928da0
test
auht Apr 8, 2025
88e3518
Pretty printer changes from meeting
LPTK Apr 11, 2025
f77ddbb
dnf disjointness
auht Apr 14, 2025
f009711
fix if
auht Apr 16, 2025
fd21398
fix if
auht Apr 16, 2025
4dc8cd7
fix missing constraints
auht Apr 18, 2025
0ed746e
test
auht Apr 18, 2025
836f3bb
elim branches
auht Apr 20, 2025
a9c4221
negtype and wip test
auht Apr 22, 2025
3bfe1c4
wip test explanation
auht Apr 22, 2025
91ac0d4
Merge remote-tracking branch 'upstream/hkmc2' into logic-subtyping
auht Apr 22, 2025
99b465b
rcd union neg disjointess
auht Apr 28, 2025
9e13a34
Merge remote-tracking branch 'upstream/hkmc2' into logic-subtyping
auht Apr 28, 2025
afb08c5
wf check and typing function intersection
auht May 4, 2025
2cfa234
Merge remote-tracking branch 'upstream/hkmc2' into logic-subtyping
auht May 4, 2025
69feb99
test
auht May 4, 2025
4a335ea
modify disjointness signature and impl
auht May 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion hkmc2/shared/src/main/scala/hkmc2/bbml/types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,14 @@ object Type:
case c@ClassLikeType(_, Nil) => (c, Top)
case ClassLikeType(c, t) => (ClassLikeType(c, t.map(_ => Wildcard.empty)), a)
case a@RcdType(_ :: _) => discriminantRcd(a)
case a@ComposedType(l, r, true) => ((discriminant(l.toBasic)._1 | discriminant(r.toBasic)._1).toBasic, a)
case a@ComposedType(l, r, true) =>
val q = (discriminant(l.toBasic)._1 | discriminant(r.toBasic)._1).toBasic
(q, (a | q.!).toBasic)
case ComposedType(l, r, false) =>
val (u, w) = discriminant(l.toBasic)
val (q, p) = discriminant(r.toBasic)
((u & q).toBasic, (w & p).toBasic)
case NegType(t) => (a, Top)
case a => (Top, a)
def disjointIU(i: Inter, u: Union)(using TL): Opt[Set[Set[InfVar -> BasicType]]] = (i.v, u.cls) match
case (S(c: ClassLikeType), cs) if cs.exists(_.name.uid === c.name.uid) => S(Set.empty)
Expand Down
161 changes: 161 additions & 0 deletions hkmc2/shared/src/test/mlscript/logicsub/elixir.mls
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
:bbml
//│ Type: ⊤

//│ Type: ⊤
// The Design Principles of the Elixir Type System
// https://www.irif.fr/~gc/papers/elixir-type-design.pdf

class
Nil()
Cons[A, B](val car: A, val cdr: B)
Tru()
Fls()
//│ Type: ⊤

let tru = new Tru
let fls = new Fls
fun not: Tru | Fls -> Tru | Fls
fun not(x) = if x is
Tru then fls
Fls then tru
fun car(x) = x.Cons#car
fun cdr(x) = x.Cons#cdr
//│ Type: ⊤



fun negate: Int -> Int
fun negate(x) = if x is
Int then 0 - x
//│ Type: ⊤

fun subtract: (Int, Int) -> Int
fun subtract(a, b) = if
a is Int and b is Int then a + negate(b)
//│ Type: ⊤

fun negate: Int | Tru | Fls -> Int | Tru | Fls
fun negate(x) = if x is
Int then 0 - x
Tru then not(x)
Fls then not(x)
//│ Type: ⊤

:e
fun subtract: (Int, Int) -> Int
fun subtract(a, b) = if
a is Int and b is Int then a + negate(b)
//│ ╔══[ERROR] Type error in `if` expression with expected type Int
//│ ║ l.47: a is Int and b is Int then a + negate(b)
//│ ║ ^^^
//│ ╙── because: cannot constrain (Int | Tru) | Fls <: Int
//│ ╔══[ERROR] Type error in `if` expression with expected type Int
//│ ║ l.47: a is Int and b is Int then a + negate(b)
//│ ║ ^^^
//│ ╙── because: cannot constrain (Int | Tru) | Fls <: Int
//│ Type: ⊤

// TODO impl
fun negate: (Int -> Int) & (Tru | Fls -> Tru | Fls)
//│ Type: ⊤

fun subtract: (Int, Int) -> Int
fun subtract(a, b) = if
a is Int and b is Int then a + negate(b)
//│ Type: ⊤

// fun negate: (Fls | Nil -> Tru) & (~(Fls | Nil) -> Fls)



// type t = [a: Int | Str, b: Tru | Fls]
// type s = [a: Int, b: Tru | Fls] | [a: Str, b: Tru | Fls]
// s = t
// fun apply: (t -> t, s) -> s
fun apply: (([a: Int | Str, b: Tru | Fls]) -> [a: Int | Str, b: Tru | Fls], [a: Int, b: Tru | Fls] | [a: Str, b: Tru | Fls]) ->
[a: Int, b: Tru | Fls] | [a: Str, b: Tru | Fls]
fun apply(f, x) = f(x)
//│ Type: ⊤



data class Ls[A](prim: [R] -> (() -> R, (A, Ls[A]) -> R) -> R)
fun nil() = new Ls((n, _) => n())
fun cons(p, q) = new Ls((n, r) => r(p, q))
fun from(x) = x.Ls#prim(() => new Nil, (x, y) => new Cons(x, from(y)))
//│ Type: ⊤

fun _in(x) = if x is
Nil then nil()
Cons then cons(car(x), cdr(x))
fun _out(x) = x.Ls#prim(() => new Nil, (x, y) => new Cons(x, y))
//│ Type: ⊤

// fun map: [A, B] -> (Ls[A], A -> B) -> Ls[B]
fun map(xs, f) =
let x = _out(xs)
if x is
Cons then cons(f(car(x)), map(cdr(x), f))
Nil then nil()
//│ Type: ⊤

// fun reduce: [A, B] -> (Ls[A], B, (A, B) -> B) -> B
fun reduce(xs, acc, f) =
let x = _out(xs)
if x is
Cons then reduce(cdr(x), f(car(x), acc), f)
Nil then acc
//│ Type: ⊤

let xs = cons(1, cons(4, nil()))
//│ Type: ⊤

xs map(negate)
//│ Type: Ls['A] | Ls['A1]
//│ Where:
//│ Int <: 'A1
//│ 'A1 <: 'A
//│ 'A <: 'A1

fun map(xs, f) = if xs is
Cons then cons(f(car(xs)), map(_out(cdr(xs)), f))
Nil then nil()
//│ Type: ⊤

fun reduce: [A, B] -> ((Cons[A, Ls[A]], B, (A, B) -> B) -> B) & ((Nil, B, Any) -> B)
fun reduce(xs, acc, f) = if xs is
Cons then reduce(_out(cdr(xs)), f(car(xs), acc), f)
Nil then acc
//│ Type: ⊤

reduce(new Nil, 1, "function")
//│ Type: Int

let xs = cons(1, cons(4, nil()))
//│ Type: ⊤

xs _out() map(negate)
//│ Type: Ls['A] | Ls['A1]
//│ Where:
//│ Int <: 'A1
//│ 'A1 <: 'A
//│ 'A <: 'A1



// TODO
// fun negate: (Int -> Int) & (Bool -> Bool) & (~(Int | Bool) -> ~(Int | Bool))
fun negate(x) = if x is
Int then 0 - x
Tru then not(x)
Fls then not(x)
else
x
//│ Type: ⊤

negate as Int -> Int
negate as Bool -> Bool
negate as ~(Int | Bool) -> ~(Int | Bool)
//│ Type: (¬Int & ¬Bool) ->{⊥} ¬Int & ¬Bool

// type tree(a) = (a and not list()) or [tree(a)]
Loading