BF:BFD[
5.1] → [
5.3516:3549]
BF:BFD[
5.3549] → [
5.1334:1334]
B:BD[
5.1334] → [
5.1335:1482]
∅:D[
3.648] → [
5.1516:1783]
B:BD[
5.1516] → [
5.1516:1783]
∅:D[
3.678] → [
5.1811:1827]
B:BD[
5.1811] → [
5.1811:1827]
∅:D[
3.736] → [
5.1873:1889]
B:BD[
5.1873] → [
5.1873:1889]
∅:D[
3.774] → [
5.1925:2054]
B:BD[
5.1925] → [
5.1925:2054]
∅:D[
3.863] → [
5.2194:2312]
B:BD[
5.2194] → [
5.2194:2312]
∅:D[
3.940] → [
5.2368:2385]
B:BD[
5.2368] → [
5.2368:2385]
∅:D[
3.968] → [
5.2411:2643]
B:BD[
5.2411] → [
5.2411:2643]
∅:D[
3.1189] → [
5.2698:2714]
B:BD[
5.2698] → [
5.2698:2714]
∅:D[
3.1290] → [
5.2750:2895]
B:BD[
5.2750] → [
5.2750:2895]
∅:D[
3.1372] → [
5.2975:2993]
B:BD[
5.2975] → [
5.2975:2993]
∅:D[
3.1420] → [
5.3039:3056]
B:BD[
5.3039] → [
5.3039:3056]
∅:D[
3.1466] → [
5.3100:3101]
B:BD[
5.3100] → [
5.3100:3101]
∅:D[
3.1553] → [
5.3185:3254]
B:BD[
5.3185] → [
5.3185:3254]
∅:D[
3.1608] → [
5.3312:3327]
B:BD[
5.3312] → [
5.3312:3327]
∅:D[
3.1799] → [
5.3509:3515]
B:BD[
5.3509] → [
5.3509:3515]
B:BD[
5.3327] → [
3.1609:1799]
B:BD[
5.3254] → [
3.1554:1608]
B:BD[
5.3101] → [
3.1467:1553]
B:BD[
5.3056] → [
3.1421:1466]
B:BD[
5.2993] → [
3.1373:1420]
B:BD[
5.2895] → [
3.1291:1372]
B:BD[
5.2714] → [
3.1190:1290]
B:BD[
5.2643] → [
3.969:1189]
B:BD[
5.2385] → [
3.941:968]
B:BD[
5.2312] → [
3.864:940]
B:BD[
5.2054] → [
3.775:863]
B:BD[
5.1889] → [
3.737:774]
B:BD[
5.1827] → [
3.679:736]
B:BD[
5.1783] → [
3.649:678]
B:BD[
5.1482] → [
3.614:648]
open Belt
open Data
let _genSymCtr = ref(0)
let genSym = (~prefix="var", ()): string => {
let num = _genSymCtr.contents
_genSymCtr := num + 1
}
let rec isSubtype = (ctx: context, tyA: typ, tyB: typ): result<context, string> => {
switch (tyA, tyB) {
| (_, _) => failwith("TODO")
}
}
and typecheck = (ctx: context, term: term, typ: typ): result<context, string> => {
switch (term, typ) {
// 1I rule
// ∀I rule
// →I rule
let augmentedCtx = ctx->List.add(TermAnnot(x, tyA))
typecheck(augmentedCtx, e, tyB)->Result.map(_ => ctx)
// Sub rule
}
}
and synthesize = (ctx: context, term: term): result<(typ, context), string> => {
switch term {
// Var rule
// 1I⇒ rule
// Anno rule
| Annot(e, tyA) => typecheck(ctx, e, tyA)->Result.map(ctx => (tyA, ctx))
// →I⇒ rule
| Lam(x, e) =>
// TODO: Check x and e
let exA = genSym(~prefix="ex", ())
let exB = genSym(~prefix="ex", ())
// →E rule
}
}
and appSynthesize = (ctx: context, funTy: typ, term: term): result<(typ, context), string> => {
switch (funTy, term) {
// →App rule
// ∀App rule
// âApp rule
}
}
// Figure 8. Applying a context, as a substitution, to a type
switch typ {
}
}
| TUnit => TUnit
| TVar(x) => TVar(x)
| TExistential(_) => failwith("TODO")
| TPolytype(_) => failwith("TODO")
| TArrow(a, b) => TArrow(applyContext(ctx, a), applyContext(ctx, b))
and applyContext = (ctx: context, typ: typ): typ => {
| (TUnit | TVar(_), _) => Error("trying to appSynthesize with a non-function type")
| (TExistential(_), _) => failwith("TODO")
| (TPolytype(a, tyA), e) => failwith("TODO")
| (TArrow(tyA, tyC), e) => typecheck(ctx, e, tyA)->Result.map(_ => (tyC, ctx))
| App(e1, e2) => synthesize(ctx, e1)->Result.flatMap(((tyA, ctx)) => appSynthesize(ctx, tyA, e2))
let augmentedCtx = list{TermAnnot(x, TVar(exA)), TypeVar(exB), TypeVar(exA), ...ctx}
typecheck(augmentedCtx, e, TVar(exB))->Result.map(_ => (
TArrow(TExistential(exA), TExistential(exB)),
ctx,
))
| Unit => Ok(TUnit, ctx)
| Var(name) => lookupTypeVariable(ctx, name)->Result.map(ty => (ty, ctx))
| (_, _) =>
let tyA = synthesize(ctx, term)
let tyA' = applyContext(ctx, tyA)
| (Lam(x, e), TArrow(tyA, tyB)) =>
| (e, TPolytype(x, tyA)) => failwith("TODO ∀I-rule")
| (Unit, TUnit) => Ok(ctx)
`${prefix}${num->Int.toString}`