(let* [(func-type (env-lookup env (car x)))
(return-type (fresh-tvar))
(other-func-type `(abs ,func-type ,return-type))
- (cs (~ func-type other-func-type))]
- (list cs return-type))
+ (cs (~ func-type other-func-type))
+ (resolved-return-type (substitute cs return-type))]
+ (list cs resolved-return-type))
; regular function
(let* ((arg-type-res (check env (cadr x)))
; TODO: what's the most appropriate substitution?
; should all constraints just be limited to a pair?
+ ; this is currently horrific and i don't know what im doing.
+ ; should probably use ast-find here or during consolidation
+ ; to detect substitutions more than one layer deep
+ ; e.g. (abs t1 int) ~ (abs bool int)
+ ; substituting these constraints with t1 should resolve t1 with bool
(define (substitute cs t)
; gets the first concrete type
; otherwise returns the last type variable
+ ; removes t itself from cs, to prevent infinite recursion
(define cs-without-t
(map (lambda (c)
(filter (lambda (x) (not (eqv? t x))) c))
(lambda (acc c)
(if (tvar? c) acc #f))]
[test (lambda (acc c)
- (and acc (fold-left test-kind #t c)))])
+ (and acc
+ (fold-left test-kind #t c) ; check only tvar substitutions
+ (<= (length c) 2)))]) ; check maximum 2 subs per equality group
(fold-left test #t cs)))))
; input: a list of binds ((x . y) (y . 3))