Skip to content

Commit 7f3fbe9

Browse files
bennnlexi-lambda
authored andcommitted
adt: add integer patterns
1 parent c87e842 commit 7f3fbe9

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

hackett-lib/hackett/private/adt.rkt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@
200200
(struct pat-hole pat-base () #:transparent)
201201
(struct pat-con pat-base (constructor pats) #:transparent)
202202
(struct pat-str pat-base (str) #:transparent)
203+
(struct pat-int pat-base (int) #:transparent)
203204
(define pat? pat-base?)
204205

205206
(define-syntax-class pat
@@ -266,6 +267,9 @@
266267
#:attr disappeared-uses '()]
267268
[pattern str:str
268269
#:attr pat (pat-str this-syntax #'str)
270+
#:attr disappeared-uses '()]
271+
[pattern int:integer
272+
#:attr pat (pat-int this-syntax #'int)
269273
#:attr disappeared-uses '()])
270274

271275
(define/contract (pat⇒! pat)
@@ -284,7 +288,9 @@
284288
(let ([a^ (generate-temporary)])
285289
(values #`(#%type:wobbly-var #,a^) '() #{values #'_ %}))]
286290
[(pat-str _ str)
287-
(values (expand-type #'String) '() #{values str %})]
291+
(values (expand-type #'String) '() #{values #`(app force- #,str) %})]
292+
[(pat-int _ int)
293+
(values (expand-type #'Integer) '() #{values #`(app force- #,int) %})]
288294
[(pat-con _ con pats)
289295
(let*-values ([(τs_args τ_result) (data-constructor-args/result! con)]
290296
[(assumps mk-pats) (pats⇐! pats τs_args)])
@@ -431,7 +437,8 @@
431437

432438
; TODO: better exhaustiveness checking on strings. OCaml checks for the strings "*", "**",
433439
; "***" etc. It would be fairly easy to do the same using splitting.
434-
[(pat-str _ s) #f])))
440+
[(pat-str _ s) #f]
441+
[(pat-int _ i) #f])))
435442

436443

437444
; Checks if patterns are exhaustive or not. Given a list of pattern-lists, returns #f if no
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#lang hackett
2+
3+
(require hackett/private/test)
4+
5+
(defn small-int? : {Integer -> Bool}
6+
[[0] True]
7+
[[1] True]
8+
[[2] True]
9+
[[_] False])
10+
11+
(test {(small-int? 0) ==! True})
12+
(test {(small-int? 2) ==! True})
13+
(test {(small-int? 4) ==! False})
14+
15+
(defn zero-or-none? : {(Maybe Integer) -> Bool}
16+
[[Nothing] True]
17+
[[(Just 0)] True]
18+
[[_] False])
19+
20+
(test {(zero-or-none? Nothing) ==! True})
21+
(test {(zero-or-none? (Just 0)) ==! True})
22+
(test {(zero-or-none? (Just 2)) ==! False})
23+
24+
(defn special-list? : {(List Integer) -> Bool}
25+
[[(:: 2 (:: n Nil))] {2 == n}]
26+
[[_] False])
27+
28+
(test {(special-list? (:: 2 (:: 2 Nil))) ==! True})
29+
(test {(special-list? (:: 2 (:: 3 Nil))) ==! False})
30+
(test {(special-list? (:: 3 (:: 2 Nil))) ==! False})
31+
32+
(defn fact : {Integer -> Integer}
33+
[[0] 1]
34+
[[n] (* n (fact (- n 1)))])
35+
36+
(test {(fact 2) ==! 2})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#lang hackett
2+
3+
(require hackett/private/test)
4+
5+
;; The purpose of `countA` is to be a recursive function that makes enough
6+
;; recursive calls to "run forever" if string patterns aren't forced
7+
(defn countA : {String -> Integer}
8+
[[""] 0]
9+
[["A"] 1]
10+
[[other] (+ (countA (head! (string-split "B" other)))
11+
(countA (head! (tail! (string-split "B" other)))))])
12+
13+
(test {(countA "ABA") ==! 2})

0 commit comments

Comments
 (0)