infer-variances.mlish (10203B)
1 #lang s-exp "../../mlish.rkt" 2 (require "../rackunit-typechecking.rkt") 3 4 (define-type T1 t1) 5 ;; No type arguments to determine variance for. 6 7 (check-type t1 : T1 -> t1) 8 9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 10 11 ;; Non-Recursive Types 12 13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 14 15 (define-type (T2 X) t2) 16 ;; X should be inferred to be irrelevant within (T2 X). 17 ;; That means it should be both covariant and contravariant. 18 19 ;; This checks that X is covariant within (T2 X). 20 (define (t2* → (T2 X)) t2) 21 (define (t2** → (→ (T2 X))) (inst t2* X)) 22 (check-type (t2**) : (→/test (T2 X))) 23 24 ;; This checks that X is contravariant within (T2 X), 25 ;; by checking that X is covariant within (→ (T2 X) Int). 26 (define (t2->int [t2 : (T2 X)] → Int) 0) 27 (define (t2->int* → (→ (T2 X) Int)) (inst t2->int X)) 28 (check-type (t2->int*) : (→/test (T2 X) Int)) 29 30 ;; This checks that X is irrelevant, even within a Ref type, 31 ;; by checking that X is covariant within (Ref (T2 X)). 32 ;; This is still sound because a value of type (Ref (T2 X)) will never 33 ;; contain anything of type X anyway. X is irrelevant within it. 34 (define (ref-t2* → (Ref (T2 X))) (ref (t2 {X}))) 35 (define (ref-t2** → (→ (Ref (T2 X)))) (inst ref-t2* X)) 36 (check-type (ref-t2**) : (→/test (Ref (T2 X)))) 37 38 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 39 40 (define-type (T3 X) t3-none (t3-some X)) 41 ;; X should be inferred to be covariant within (T3 X). 42 43 ;; This checks that X is covariant within (T3 X). 44 (define (t3-none* → (T3 X)) t3-none) 45 (define (t3-none** → (→ (T3 X))) (inst t3-none* X)) 46 (check-type (t3-none**) : (→/test (T3 X))) 47 48 ;; This checks that X is not contravariant within (T3 X), 49 ;; by checking that X is not covariant within (→ (T3 X) Int). 50 (define (t3->int [t3 : (T3 X)] → Int) 0) 51 (define (t3->int* → (→ (T3 X) Int)) (inst t3->int X)) 52 (typecheck-fail (t3->int*)) 53 54 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 55 56 (define-type (T4 X) t4-none (t4-some (→ X Int))) 57 ;; X should be inferred to be contravariant within (T4 X). 58 59 ;; This checks that X is not covariant within (T4 X). 60 (define (t4-none* → (T4 X)) t4-none) 61 (define (t4-none** → (→ (T4 X))) (inst t4-none* X)) 62 (typecheck-fail (t4-none**)) 63 64 ;; This checks that X is contravariant within (T4 X), 65 ;; by checking that X is covariant within (→ (T4 X) Int). 66 (define (t4->int [t4 : (T4 X)] → Int) 0) 67 (define (t4->int* → (→ (T4 X) Int)) (inst t4->int X)) 68 (check-type (t4->int*) : (→/test (T4 X) Int)) 69 70 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 71 72 (define-type (T5 X) t5-none (t5-some+ X) (t5-some- (→ X Int))) 73 ;; X should be inferred to be invariant within (T5 X). 74 75 ;; This checks that X is not covariant within (T5 X). 76 (define (t5-none* → (T5 X)) t5-none) 77 (define (t5-none** → (→ (T5 X))) (inst t5-none* X)) 78 (typecheck-fail (t5-none**)) 79 80 ;; This checks that X is not contravariant within (T5 X), 81 ;; by checking that X is not covariant within (→ (T5 X) Int). 82 (define (t5->int [t5 : (T5 X)] → Int) 0) 83 (define (t5->int* → (→ (T5 X) Int)) (inst t5->int X)) 84 (typecheck-fail (t5->int*)) 85 86 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 87 88 ;; Recursive Types 89 90 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 91 92 (define-type (T6 X) t6-none (t6-same (T6 X))) 93 ;; X should be inferred to be irrelevant within (T6 X). 94 95 ;; This checks that X is covariant within (T6 X). 96 (define (t6-none* → (T6 X)) t6-none) 97 (define (t6-none** → (→ (T6 X))) (inst t6-none* X)) 98 (check-type (t6-none**) : (→/test (T6 X))) 99 100 ;; This checks that X is contravariant within (T6 X), 101 ;; by checking that X is covariant within (→ (T6 X) Int). 102 (define (t6->int [t6 : (T6 X)] → Int) 0) 103 (define (t6->int* → (→ (T6 X) Int)) (inst t6->int X)) 104 (check-type (t6->int*) : (→/test (T6 X) Int)) 105 106 ;; This checks that X is irrelevant, even within a Ref type, 107 ;; by checking that X is covariant within (Ref (T6 X)). 108 ;; This is still sound because a value of type (Ref (T6 X)) will never 109 ;; contain anything of type X anyway. X is irrelevant within it. 110 (define (ref-t6* → (Ref (T6 X))) (ref (t6-none {X}))) 111 (define (ref-t6** → (→ (Ref (T6 X)))) (inst ref-t6* X)) 112 (check-type (ref-t6**) : (→/test (Ref (T6 X)))) 113 114 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 115 116 (define-type (T7 X) t7-none (t7-weird (→ (T7 X) Int))) 117 (define-type (T8 X) t8-none (t8-weird (T8 (→ X Int)))) 118 (define-type (T9 X) t9-none (t9-weird (→ (T9 (→ X Int)) Int))) 119 ;; X should be inferred to be irrelevant within (T7 X), (T8 X), and 120 ;; (T9 X). None of these types could contain or recieve an actual X. 121 122 (define-type (T10 X) (t10 (T7 X) (T8 X) (T9 X))) 123 ;; So because of that, X should be irrelevant within (T10 X). 124 125 ;; This checks that X is covariant within (T10 X). 126 (define (t10-none* → (T10 X)) (t10 t7-none t8-none t9-none)) 127 (define (t10-none** → (→ (T10 X))) (inst t10-none* X)) 128 (check-type (t10-none**) : (→/test (T10 X))) 129 130 ;; This checks that X is contravariant within (T10 X), 131 ;; by checking that X is covariant within (→ (T10 X) Int). 132 (define (t10->int [t10 : (T10 X)] → Int) 0) 133 (define (t10->int* → (→ (T10 X) Int)) (inst t10->int X)) 134 (check-type (t10->int*) : (→/test (T10 X) Int)) 135 136 ;; This checks that X is irrelevant, even within a Ref type, 137 ;; by checking that X is covariant within (Ref (T10 X)). 138 ;; This is still sound because a value of type (Ref (T10 X)) will never 139 ;; contain anything of type X anyway. X is irrelevant within it. 140 (define (ref-t10* → (Ref (T10 X))) (ref (t10 (t7-none {X}) (t8-none {X}) (t9-none {X})))) 141 (define (ref-t10** → (→ (Ref (T10 X)))) (inst ref-t10* X)) 142 (check-type (ref-t10**) : (→/test (Ref (T10 X)))) 143 144 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 145 146 (define-type (T11 X) t11-none (t11+ X) (t11-weird (→ (T11 X) Int))) 147 (define-type (T12 X) t12-none (t12+ X) (t12-weird (T12 (→ X Int)))) 148 (define-type (T13 X) t13-none (t13+ X) 149 (t13-weird (→ (T13 (→ X Int)) Int))) 150 (define-type (T14 X) t14-none (t14- (→ X Int)) 151 (t14-weird (→ (T14 (→ X Int)) Int))) 152 ;; X should be inferred to be invariant within (T11 X) and (T12 X), 153 ;; but covariant within (T13 X), and contravariant within (T14 X). 154 155 ;; This checks that X is covariant within (T13 X), but not any of the 156 ;; others. 157 (define (t11-none* → (T11 X)) t11-none) 158 (define (t12-none* → (T12 X)) t12-none) 159 (define (t13-none* → (T13 X)) t13-none) 160 (define (t14-none* → (T14 X)) t14-none) 161 (define (t11-none** → (→ (T11 X))) (inst t11-none* X)) 162 (define (t12-none** → (→ (T12 X))) (inst t12-none* X)) 163 (define (t13-none** → (→ (T13 X))) (inst t13-none* X)) 164 (define (t14-none** → (→ (T14 X))) (inst t14-none* X)) 165 (typecheck-fail (t11-none**)) 166 (typecheck-fail (t12-none**)) 167 (check-type (t13-none**) : (→/test (T13 X))) 168 (typecheck-fail (t14-none**)) 169 170 ;; This checks that X is contravariant within (T14 X), but not any of 171 ;; the others. 172 (define (t11->int [t11 : (T11 X)] → Int) 0) 173 (define (t12->int [t12 : (T12 X)] → Int) 0) 174 (define (t13->int [t13 : (T13 X)] → Int) 0) 175 (define (t14->int [t14 : (T14 X)] → Int) 0) 176 (define (t11->int* → (→ (T11 X) Int)) (inst t11->int X)) 177 (define (t12->int* → (→ (T12 X) Int)) (inst t12->int X)) 178 (define (t13->int* → (→ (T13 X) Int)) (inst t13->int X)) 179 (define (t14->int* → (→ (T14 X) Int)) (inst t14->int X)) 180 (typecheck-fail (t11->int*)) 181 (typecheck-fail (t12->int*)) 182 (typecheck-fail (t13->int*)) 183 (check-type (t14->int*) : (→/test (T14 X) Int)) 184 185 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 186 187 (define-type (T15 X) t15-none (t15-cons+ X (T15 X))) 188 (define-type (T16 X) t16-none (t16-cons- (→ X Int) (T16 X))) 189 ;; X should be inferred to be covariant within (T15 X), and 190 ;; contravariant within (T16 X). (T15 X) is just like a (List X) type, 191 ;; and (T16 X) is just like a (List (→ X Int)). 192 193 ;; This checks that X is covariant within (T15 X). 194 (define (t15-none* → (T15 X)) t15-none) 195 (define (t15-none** → (→ (T15 X))) (inst t15-none* X)) 196 (check-type (t15-none**) : (→/test (T15 X))) 197 ;; This checks that X is not covariant within (T16 X). 198 (define (t16-none* → (T16 X)) t16-none) 199 (define (t16-none** → (→ (T16 X))) (inst t16-none* X)) 200 (typecheck-fail (t16-none**)) 201 202 ;; This checks that X is not contravariant within (T15 X), 203 ;; by checking that X is not covariant within (→ (T15 X) Int). 204 (define (t15->int [t15 : (T15 X)] → Int) 0) 205 (define (t15->int* → (→ (T15 X) Int)) (inst t15->int X)) 206 (typecheck-fail (t15->int*)) 207 ;; This checks that X is contravariant within (T16 X), 208 ;; by checking that X is covariant within (→ (T16 X) Int). 209 (define (t16->int [t16 : (T16 X)] → Int) 0) 210 (define (t16->int* → (→ (T16 X) Int)) (inst t16->int X)) 211 (check-type (t16->int*) : (→/test (T16 X) Int)) 212 213 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 214 215 ;; Mutually Recursive Types 216 217 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 218 219 (define-type (T17 X) (t17-some X) (t18 (T18 X))) 220 (define-type (T18 X) t18-none (t18-cons (T17 X) (T18 X))) 221 ;; X should be inferred to be covariant in both (T17 X) and (T18 X). 222 ;; This is similar to an arbitrary-arity tree type. 223 224 ;; This checks that X is covariant within (T17 X). 225 (define (t17-none* → (T17 X)) (t18 t18-none)) 226 (define (t17-none** → (→ (T17 X))) (inst t17-none* X)) 227 (check-type (t17-none**) : (→/test (T17 X))) 228 ;; This checks that X is covariant within (T18 X). 229 (define (t18-none* → (T18 X)) t18-none) 230 (define (t18-none** → (→ (T18 X))) (inst t18-none* X)) 231 (check-type (t18-none**) : (→/test (T18 X))) 232 233 ;; This checks that X is not contravariant within (T17 X), 234 ;; by checking that X is not covariant within (→ (T17 X) Int). 235 (define (t17->int [t17 : (T17 X)] → Int) 0) 236 (define (t17->int* → (→ (T17 X) Int)) (inst t17->int X)) 237 (typecheck-fail (t17->int*)) 238 ;; This checks that X is not contravariant within (T18 X), 239 ;; by checking that X is not covariant within (→ (T18 X) Int). 240 (define (t18->int [t18 : (T18 X)] → Int) 0) 241 (define (t18->int* → (→ (T18 X) Int)) (inst t18->int X)) 242 (typecheck-fail (t18->int*)) 243