find.mlish (2426B)
1 #lang s-exp "../../mlish.rkt" 2 (require "../rackunit-typechecking.rkt") 3 4 (define-type (List X) 5 Nil 6 (Cons X (List X))) 7 8 (define-type (Option X) 9 None 10 (Some X)) 11 12 (define (find [lst : (List X)] [pred : (→ X Bool)] → (Option X)) 13 (match lst with 14 [Nil -> None] 15 [Cons fst rst -> 16 (cond [(pred fst) (Some fst)] 17 [else (find rst pred)])])) 18 19 (check-type 20 (find (Cons 1 (Cons 2 (Cons 3 Nil))) (λ ([x : Int]) (<= 2 x))) 21 : (Option Int) 22 -> (Some 2)) 23 24 (check-type 25 (find (Cons 1 (Cons 0 (Cons -1 Nil))) (λ ([x : Int]) (<= 2 x))) 26 : (Option Int) 27 -> None) 28 29 ;; args inferred in order, L-to-R, currently no backtracking 30 (check-type 31 (find Nil (λ ([x : Int]) (<= 2 x))) 32 : (Option Int) 33 -> None) 34 35 ;; reversing arg order leads to successful inference 36 (define (find2 [pred : (→ X Bool)] [lst : (List X)] → (Option X)) 37 (match lst with 38 [Nil -> None] 39 [Cons fst rst -> 40 (cond [(pred fst) (Some fst)] 41 [else (find2 pred rst)])])) 42 43 (check-type 44 (find2 (λ ([x : Int]) (<= 2 x)) Nil) 45 : (Option Int) 46 -> None) 47 48 (define (find-min/max [lst : (List X)] [<? : (→ Y Y Bool)] [extract-key : (→ X Y)] 49 → (Option (× X X))) 50 (match lst with 51 [Nil -> None] 52 [Cons x1 rst -> 53 (let ([y1 (extract-key x1)]) 54 (Some (find-min/max-accum rst <? extract-key x1 y1 x1 y1)))])) 55 56 (define (find-min/max-accum [lst : (List X)] [<? : (→ Y Y Bool)] [extract-key : (→ X Y)] 57 [x-min : X] [y-min : Y] [x-max : X] [y-max : Y] 58 → (× X X)) 59 (match lst with 60 [Nil -> (tup x-min x-max)] 61 [Cons x2 rst -> 62 (let ([y2 (extract-key x2)]) 63 (cond [(<? y2 y-min) 64 (find-min/max-accum rst <? extract-key x2 y2 x-max y-max)] 65 [(<? y-max y2) 66 (find-min/max-accum rst <? extract-key x-min y-min x2 y2)] 67 [else 68 (find-min/max-accum rst <? extract-key x-min y-min x-max y-max)]))])) 69 70 (check-type 71 (find-min/max (Nil {Int}) 72 (λ ([x : Int] [y : Int]) 73 (< x y)) 74 (λ ([x : Int]) 75 x)) 76 : (Option (× Int Int)) 77 -> None) 78 79 (check-type 80 (find-min/max (Cons 1 (Cons 2 (Cons 3 Nil))) 81 (λ ([x : Int] [y : Int]) 82 (< x y)) 83 (λ ([x : Int]) 84 x)) 85 : (Option (× Int Int)) 86 -> (Some (tup 1 3))) 87