www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 75da160c2d510c934e6d8c24c542e3e3edaf5e9e
parent fbc5934675db6fa19b9feb079f74b143d3d55acd
Author: Stephen Chang <stchang@ccs.neu.edu>
Date:   Thu, 17 Dec 2015 16:16:09 -0500

finish nqueens example for infer.rkt

Diffstat:
Mtapl/ext-stlc.rkt | 16++++++++++++----
Mtapl/stlc+cons.rkt | 10++++++++--
Mtapl/tests/infer-tests.rkt | 48+++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 67 insertions(+), 7 deletions(-)

diff --git a/tapl/ext-stlc.rkt b/tapl/ext-stlc.rkt @@ -82,14 +82,22 @@ (⊢ e- : ascribed-τ)]) (define-typed-syntax let/tc #:export-as let - [(_ ([x e] ...) e_body) + [(~and l (_ ([x e] ...) e_body)) + #:with τ-expected (get-expected-type #'l) #:with ((e- τ) ...) (infers+erase #'(e ...)) - #:with ((x- ...) e_body- τ_body) (infer/ctx+erase #'([x τ] ...) #'e_body) + #:with ((x- ...) e_body- τ_body) (infer/ctx+erase #'([x τ] ...) #'(add-expected e_body τ-expected)) (⊢ (let ([x- e-] ...) e_body-) : τ_body)]) +; dont need to manually transfer expected type +; result template automatically propagates properties +; - only need to transfer expected type when local expanding an expression +; - see let/tc (define-typed-syntax let*/tc #:export-as let* - [(_ () e_body) #'e_body] - [(_ ([x e] [x_rst e_rst] ...) e_body) + [(~and l (_ () e_body)) + #:with τ-expected (get-expected-type #'l) + #'e_body] + [(~and l (_ ([x e] [x_rst e_rst] ...) e_body)) + #:with τ-expected (get-expected-type #'l) #'(let/tc ([x e]) (let*/tc ([x_rst e_rst] ...) e_body))]) (define-typed-syntax letrec diff --git a/tapl/stlc+cons.rkt b/tapl/stlc+cons.rkt @@ -51,4 +51,10 @@ (⊢ (cdr e-) : τ-lst)]) (define-typed-syntax list/tc #:export-as list [(_) #'nil/tc] - [(_ x . rst) #'(cons/tc x (list/tc . rst))]) -\ No newline at end of file + [(~and lst (_ x . rst)) ; has expected type + #:with expected-τ (get-expected-type #'lst) + #:when (syntax-e #'expected-τ) + #:with (~List τ) (local-expand #'expected-τ 'expression null) + #'(cons/tc (add-expected x τ) (list/tc . rst))] + [(_ x . rst) ; no expected type + #'(cons/tc x (list/tc . rst))]) +\ No newline at end of file diff --git a/tapl/tests/infer-tests.rkt b/tapl/tests/infer-tests.rkt @@ -113,11 +113,31 @@ (if (nil? lst) #t (and (p? (hd lst)) (all? p? (tl lst))))) - + +(define {X} (tails [lst : (List X)] → (List (List X))) + (if (nil? lst) + (list nil) + (cons lst (tails (tl lst))))) + +; creates backwards list +(define {X} (build-list [n : Int] [f : (→ Int X)] → (List X)) + (if (zero? (sub1 n)) + (list (f 0)) + (cons (f (sub1 n)) (build-list (sub1 n) f)))) +(check-type (build-list 1 add1) : (List Int) ⇒ (list 1)) +(check-type (build-list 3 add1) : (List Int) ⇒ (list 3 2 1)) +(check-type (build-list 5 sub1) : (List Int) ⇒ (list 3 2 1 0 -1)) + +(define {X} (append [lst1 : (List X)] [lst2 : (List X)] → (List X)) + (if (nil? lst1) + lst2 + (cons (hd lst1) (append (tl lst1) lst2)))) + ; nqueens (define-type-alias Queen (× Int Int)) (define (q-x [q : Queen] → Int) (proj q 0)) (define (q-y [q : Queen] → Int) (proj q 1)) +(define (Q [x : Int] [y : Int] → Queen) (tup x y)) (define (safe? [q1 : Queen] [q2 : Queen] → Bool) (let ([x1 (q-x q1)][y1 (q-y q1)] @@ -128,6 +148,32 @@ #t (let ([q1 (hd qs)]) (all? (λ ([q2 : Queen]) (safe? q1 q2)) (tl qs))))) +(define (valid? [lst : (List Queen)] → Bool) + (all? safe/list? (tails lst))) + +(define (nqueens [n : Int] → (List Queen)) + (let* ([process-row + (λ ([r : Int] [all-possible-so-far : (List (List Queen))]) + (foldr + (λ ([qs : (List Queen)] [new-qss : (List (List Queen))]) + (append + (map + (λ ([c : Int]) (cons (Q r c) qs)) + (build-list n add1)) + new-qss)) + nil + all-possible-so-far))] + [all-possible (foldl process-row (list nil) (build-list n add1))]) + (let ([solns (filter valid? all-possible)]) + (if (nil? solns) + nil + (hd solns))))) + +(check-type (nqueens 1) : (List Queen) ⇒ (list (list 1 1))) +(check-type (nqueens 2) : (List Queen) ⇒ (nil {Queen})) +(check-type (nqueens 3) : (List Queen) ⇒ (nil {Queen})) +(check-type (nqueens 4) : (List Queen) ⇒ (list (Q 3 1) (Q 2 4) (Q 1 2) (Q 4 3))) +(check-type (nqueens 5) : (List Queen) ⇒ (list (Q 4 2) (Q 3 4) (Q 2 1) (Q 1 3) (Q 5 5))) ; -------------------------------------------------- ; all ext-stlc tests should still pass (copied below):