ocaml: phase 5 HM tuple + list types (+7 tests, 326 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 29s

Tuple type (hm-con "*" TYPES); list type (hm-con "list" (TYPE)).
ocaml-infer-tuple threads substitution through each item left-to-right.
ocaml-infer-list unifies all items with a fresh 'a (giving 'a list for
empty []).

Pretty-printer renders 'Int * Int' for tuples and 'Int list' for lists,
matching standard OCaml notation.

Examples:
  fun x y -> (x, y) : 'a -> 'b -> 'a * 'b
  fun x -> [x; x] : 'a -> 'a list
  []                : 'a list
This commit is contained in:
2026-05-08 12:54:15 +00:00
parent a0abdcf520
commit 6d7197182e
3 changed files with 92 additions and 1 deletions

View File

@@ -145,6 +145,56 @@
{:subst sf
:type (hm-apply sf te)}))))))))))))
;; Tuple type: (hm-con "*" (list T1 T2 ...)).
(define ocaml-hm-tuple
(fn (types) (hm-con "*" types)))
;; List type: (hm-con "list" (list ELEM)).
(define ocaml-hm-list
(fn (elem) (hm-con "list" (list elem))))
(define ocaml-infer-tuple
(fn (items env counter)
(let ((subst {}) (types (list)))
(begin
(define loop
(fn (xs env-cur)
(when (not (= xs (list)))
(let ((r (ocaml-infer (first xs) env-cur counter)))
(let ((s (get r :subst)) (t (get r :type)))
(begin
(set! subst (hm-compose s subst))
(append! types t)
(loop (rest xs) (hm-apply-env s env-cur))))))))
(loop items env)
{:subst subst
:type (ocaml-hm-tuple
(map (fn (t) (hm-apply subst t)) types))}))))
(define ocaml-infer-list
(fn (items env counter)
(cond
((= (len items) 0)
{:subst {} :type (ocaml-hm-list (hm-fresh-tv counter))})
(else
(let ((subst {}) (elem-tv (hm-fresh-tv counter)))
(begin
(define loop
(fn (xs env-cur)
(when (not (= xs (list)))
(let ((r (ocaml-infer (first xs) env-cur counter)))
(let ((s (get r :subst)) (t (get r :type)))
(let ((s2 (ocaml-hm-unify
(hm-apply s elem-tv)
t
(hm-compose s subst))))
(begin
(set! subst s2)
(loop (rest xs) (hm-apply-env s2 env-cur)))))))))
(loop items env)
{:subst subst
:type (ocaml-hm-list (hm-apply subst elem-tv))}))))))
(set! ocaml-infer
(fn (expr env counter)
(let ((tag (nth expr 0)))
@@ -162,6 +212,8 @@
(nth expr 3) (nth expr 4) env counter))
((= tag "if") (ocaml-infer-if (nth expr 1) (nth expr 2)
(nth expr 3) env counter))
((= tag "tuple") (ocaml-infer-tuple (rest expr) env counter))
((= tag "list") (ocaml-infer-list (rest expr) env counter))
((= tag "neg")
(let ((r (ocaml-infer (nth expr 1) env counter)))
(let ((s (get r :subst)) (t (get r :type)))
@@ -205,5 +257,11 @@
(str "(" (ocaml-hm-format-type a) ")"))
(else (ocaml-hm-format-type a)))
" -> " (ocaml-hm-format-type b))))
((= head "*")
(let ((parts (map ocaml-hm-format-type args)))
(join " * " parts)))
((= head "list")
(let ((elem (ocaml-hm-format-type (nth args 0))))
(str elem " list")))
(else head))))
(else (str t)))))