Last active
January 25, 2022 08:13
-
-
Save adimanea/7aa7921c913e70fb9a8b1524b5bd2d3c to your computer and use it in GitHub Desktop.
P. Ragde's Proust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; P. Ragde -- Proust, a Nano Proof Assistant (2016) | |
#lang racket | |
(struct Lam (var body)) ; lambda expression | |
(struct App (func arg)) ; application | |
(struct Arrow (domain codomain)) ; function | |
(struct TA (type var)) ; type annotation | |
;; expr = (lambda x => expr) | |
;; | (expr expr) | |
;; | (expr : type) | |
;; | x | |
;; parse-expr : sexp -> Expr | |
(define (parse-expr s) | |
(match s | |
[`(lambda ,(? symbol? x) => ,e) ; is it a lambda-expression? | |
(Lam x (parse-expr e))] ; then make it Lam | |
[`(,func ,arg) ; is it an application? | |
(App (parse-expr func) ; then make it App | |
(parse-expr arg))] | |
[`(,e : ,t) (TA (parse-expr e) (parse-type t))] | |
[(? symbol? x) x])) ; otherwise, it's a symbol => return it | |
;; my tests | |
(parse-expr '(lambda x => x)) ; => #<Lam> OK | |
(parse-expr '(lambda x => (lambda y => (x y)))) ; => #<Lam> OK | |
(parse-expr '(+ x)) ; => #<App> OK | |
(parse-expr 'x) ; => 'X OK | |
;; type = (type -> type) | X | |
;; ;; parse-type : sexp -> Type | |
(define (parse-type t) | |
(match t | |
[`(,t1 -> ,t2) | |
(Arrow (parse-type t1) | |
(parse-type t2))] | |
[(? symbol? X) X] | |
[else (error "unrecognized type")])) | |
;; my tests | |
(parse-type '(A -> B)) ; => #<Arrow> OK | |
(parse-type 'X) ; => 'X OK | |
;; type-check : Context Expr Type -> boolean | |
;; produces #t if expr has type t in context ctx (else error) | |
(define (type-check ctx expr type) | |
(match expr | |
[(Lam x t) | |
(match type | |
[(Arrow tt tw) (type-check (cons `(,x ,tt) ctx) t tw)] | |
[else (cannot-check ctx expr type)])] | |
[else (if (equal? (type-infer ctx expr) type) true | |
(cannot-check ctx expr type))])) | |
(define (cannot-check ctx expr type) | |
(error "cannot check the type of the expression in the provided context")) | |
;; type-infer : Context Expr -> Type | |
;; produces type of expr in context ctx (error if it can't) | |
(define (type-infer ctx expr) | |
(match expr | |
[(Lam _ _) (cannot-infer ctx expr)] | |
[(TA e t) (type-check ctx e t) t] | |
[(App f a) | |
(define tf (type-infer ctx f)) | |
(match tf | |
[(Arrow tt tw) #:when (type-check ctx a tt) tw] | |
[else (cannot-infer ctx expr)])] | |
[(? symbol? x) | |
(cond | |
[(assoc x ctx) => second] | |
[else (cannot-infer ctx expr)])])) | |
(define (cannot-infer ctx expr) | |
(error "cannot infer the type of the expression in the provided context")) | |
;; my test | |
(type-check empty | |
(parse-expr '(lambda x => x)) | |
(parse-type '(A -> A))) ; => #t OK | |
;; ONLY WORKS FOR LAMBDAS | |
;; not working | |
(define (check-proof p) | |
(type-infer empty (parse-expr p)) true) | |
;; test: | |
(check-proof | |
`((lambda x => (lambda y => (y x))) : (A -> ((A -> B) -> B)))) ; => #t OK | |
;; not working | |
(check-proof | |
`(x : A)) | |
(check-proof | |
`((+ x) : (A -> A)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Adding a version with a few print statements, one more test, and a bunch of comments.