-
Notifications
You must be signed in to change notification settings - Fork 1
/
init.fnl
72 lines (60 loc) · 1.5 KB
/
init.fnl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
(fn has-type? [value t]
"Check if `value` has type `t`."
(if
(= :any t)
true
(and
(= :string (type t))
(= :? (string.sub t 1 1)))
(or
(= nil value)
(has-type? value (string.sub t 2)))
(or
(= :integer t)
(= :float t))
(= t (math.type value))
(= :file t)
(= :file (io.type value))
(= :closed-file t)
(= "closed file" (io.type value))
(or (= :function (type t))
(?. (getmetatable t) :__call))
(if (t value) true false)
(= :table (type t))
(accumulate [result (= :table (type value))
k v (pairs t)]
(and result (has-type? (. value k) v)))
:else
(= t (type value))))
(fn intersection [...]
"Create an intersection type."
(let [types [...]]
(fn [value]
(accumulate [result true
_ t (ipairs types)]
(and result (has-type? value t))))))
(fn union [...]
"Create a union type."
(let [types [...]]
(fn [value]
(accumulate [result false
_ t (ipairs types)]
(or result (has-type? value t))))))
(fn enum [& vals]
"Create an enum type."
(let [vals (collect [_ v (ipairs vals)] (values v true))]
(fn [value]
(. vals value))))
(fn seq [T]
"Create a sequential list type from type `T`."
(fn [value]
(if (= :table (type value))
(accumulate [result true
_ v (ipairs value)]
(and result (has-type? v T)))
false)))
{: has-type?
: intersection
: union
: enum
: seq}