Skip to content

Commit d978b7c

Browse files
authored
Merge pull request #132 from ssoelvsten/lib/List/fval-dependencies
feat: `List` features (for Facetted Values)
2 parents 54ed890 + c36a395 commit d978b7c

File tree

4 files changed

+203
-141
lines changed

4 files changed

+203
-141
lines changed

lib/List.trp

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,35 @@ let (* -- List Access -- *)
2121
fun null [] = true
2222
| null _ = false
2323

24+
(** Returns `true` if an element satisfies the given predicate. Tail-recursive. *)
25+
fun exist f [] = false
26+
| exist f x::xs = if f x then true else exist f xs
27+
28+
(** Returns `true` if an element satisfies the given predicate. Tail-recursive.
29+
*
30+
* Unlike `exist`, this runs `f` on elements even after having found a true candidate. This
31+
* raises the IFC level of the result to the same level regardless of the order of the elements
32+
* in `xs`.
33+
*)
34+
fun exist' f xs =
35+
let fun go acc [] = acc
36+
| go acc x::xs = go ((f x) orelse acc) xs
37+
in go false xs
38+
end
39+
40+
(** Returns `true` if all elements satisfy the given predicate. Tail-recursive. *)
41+
fun forall f xs = not (exist (fn x => not (f x)) xs)
42+
43+
(** Returns `true` if all elements satisfy the given predicate. Tail-recursive.
44+
*
45+
* Unlike `forall`, this runs `f` on elements even after having found a violation. This raises
46+
* the IFC level of the result to the same level regardless of the order of the elements in
47+
* `xs`.
48+
*)
49+
fun forall' f xs = not (exist' (fn x => not (f x)) xs)
50+
2451
(** Returns `true` if the element `x` exists in the list. *)
25-
fun elem x [] = false
26-
| elem x y::ys = if x = y then true else elem x ys
52+
fun elem x ys = exist (fn y => x = y) ys
2753

2854
(** Returns the length of the given list. Tail-recursive. *)
2955
fun length xs =
@@ -99,17 +125,24 @@ let (* -- List Access -- *)
99125
in if f (i,x) then x::xs' else xs' end
100126
in go 0 l end
101127

102-
(** Split the list `ls` into two sublists depending on whether each respective element
128+
(** Split the list `ls` into two reversed sublists depending on whether each respective element
103129
satisfies the predicate `f`. Tail-recursive. *)
104-
fun partition f ls =
105-
let fun partition_aux (a,b) [] = (reverse a, reverse b)
130+
fun revPartition f ls =
131+
let fun partition_aux (a,b) [] = (a, b)
106132
| partition_aux (a,b) (x::xs) =
107133
if f x
108134
then partition_aux (x::a, b) xs
109135
else partition_aux (a, x::b) xs
110136
in partition_aux ([],[]) ls
111137
end
112138

139+
(** Split the list `ls` into two sublists depending on whether each respective element satisfies
140+
the predicate `f`. Tail-recursive. *)
141+
fun partition f ls =
142+
let val (a,b) = revPartition f ls
143+
in (reverse a, reverse b)
144+
end
145+
113146
(* -- List Generation -- *)
114147

115148
(** Returns the list of elements `[0, .., n-1]`. Tail-recursive. *)
@@ -122,6 +155,16 @@ let (* -- List Access -- *)
122155

123156
(* -- Sorting -- *)
124157

158+
(** Returns the largest value in the given (non-empty) list according to the given less-than
159+
* predicate. *)
160+
fun max cmp xs = foldl1 (fn (x, currMax) => if cmp currMax x then x else currMax) xs
161+
162+
(** Returns the smallest value in the given (non-empty) list according to the given less-than
163+
* predicate. *)
164+
fun min cmp xs =
165+
let fun cmp' x y = cmp y x
166+
in max cmp' xs end
167+
125168
(** Returns a list with the same elements as in `l` but sorted based on the less-than predicate,
126169
* `cmp` of type `'a -> 'a -> bool`. *)
127170
fun sort cmp xs =
@@ -174,6 +217,10 @@ in [ ("head", head)
174217
, ("tail", tail)
175218
, ("nth", nth)
176219
, ("null", null)
220+
, ("exist", exist)
221+
, ("exist'", exist')
222+
, ("forall", forall)
223+
, ("forall'", forall')
177224
, ("elem", elem)
178225
, ("length", length)
179226
, ("reverse", reverse)
@@ -188,7 +235,10 @@ in [ ("head", head)
188235
, ("filter", filter)
189236
, ("filteri", filteri)
190237
, ("partition", partition)
238+
, ("revPartition", revPartition)
191239
, ("range", range)
240+
, ("max", max)
241+
, ("min", min)
192242
, ("sort", sort)
193243
]
194244
end

tests/lib/List.golden

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
2025-10-24T08:31:14.889Z [RTM] info: Skipping network creation. Observe that all external IO operations will yield a runtime error.
1+
2026-02-17T16:06:55.036Z [RTM] info: Skipping network creation. Observe that all external IO operations will yield a runtime error.
22
begin List
33
begin head
44
[ TEST ] it returns 42 for [42] [ PASS ] it returns 42 for [42]
@@ -22,6 +22,44 @@
2222
[ TEST ] it rejects [0,1] [ PASS ] it rejects [0,1]
2323
[ TEST ] it rejects [1,2,0] [ PASS ] it rejects [1,2,0]
2424
end 
25+
begin exist
26+
[ TEST ] it rejects isOdd [] [ PASS ] it rejects isOdd []
27+
[ TEST ] it rejects isEven [] [ PASS ] it rejects isEven []
28+
[ TEST ] it rejects isOdd [42] [ PASS ] it rejects isOdd [42]
29+
[ TEST ] it accepts isEven [42] [ PASS ] it accepts isEven [42]
30+
[ TEST ] it accepts isOdd [21, 42] [ PASS ] it accepts isOdd [21, 42]
31+
[ TEST ] it accepts isOdd [42, 21] [ PASS ] it accepts isOdd [42, 21]
32+
[ TEST ] it rejects isOdd [22, 10] [ PASS ] it rejects isOdd [22, 10]
33+
end 
34+
begin exist'
35+
[ TEST ] it rejects isOdd [] [ PASS ] it rejects isOdd []
36+
[ TEST ] it rejects isEven [] [ PASS ] it rejects isEven []
37+
[ TEST ] it rejects isOdd [42] [ PASS ] it rejects isOdd [42]
38+
[ TEST ] it accepts isEven [42] [ PASS ] it accepts isEven [42]
39+
[ TEST ] it accepts isOdd [21, 42] [ PASS ] it accepts isOdd [21, 42]
40+
[ TEST ] it accepts isOdd [42, 21] [ PASS ] it accepts isOdd [42, 21]
41+
[ TEST ] it rejects isOdd [22, 10] [ PASS ] it rejects isOdd [22, 10]
42+
end 
43+
begin forall
44+
[ TEST ] it accepts isOdd [] [ PASS ] it accepts isOdd []
45+
[ TEST ] it accepts isEven [] [ PASS ] it accepts isEven []
46+
[ TEST ] it rejects isOdd [42] [ PASS ] it rejects isOdd [42]
47+
[ TEST ] it accepts isEven [42] [ PASS ] it accepts isEven [42]
48+
[ TEST ] it rejects isOdd [21, 42] [ PASS ] it rejects isOdd [21, 42]
49+
[ TEST ] it rejects isOdd [42, 21] [ PASS ] it rejects isOdd [42, 21]
50+
[ TEST ] it rejects isOdd [22, 10] [ PASS ] it rejects isOdd [22, 10]
51+
[ TEST ] it accepts isEven [22, 10] [ PASS ] it accepts isEven [22, 10]
52+
end 
53+
begin forall'
54+
[ TEST ] it accepts isOdd [] [ PASS ] it accepts isOdd []
55+
[ TEST ] it accepts isEven [] [ PASS ] it accepts isEven []
56+
[ TEST ] it rejects isOdd [42] [ PASS ] it rejects isOdd [42]
57+
[ TEST ] it accepts isEven [42] [ PASS ] it accepts isEven [42]
58+
[ TEST ] it rejects isOdd [21, 42] [ PASS ] it rejects isOdd [21, 42]
59+
[ TEST ] it rejects isOdd [42, 21] [ PASS ] it rejects isOdd [42, 21]
60+
[ TEST ] it rejects isOdd [22, 10] [ PASS ] it rejects isOdd [22, 10]
61+
[ TEST ] it accepts isEven [22, 10] [ PASS ] it accepts isEven [22, 10]
62+
end 
2563
begin elem
2664
[ TEST ] it rejects 42 [] [ PASS ] it rejects 42 []
2765
[ TEST ] it accepts 42 [42] [ PASS ] it accepts 42 [42]
@@ -119,6 +157,10 @@
119157
[ TEST ] it isOddIdx xs [ PASS ] it isOddIdx xs
120158
[ TEST ] it isOddVal xs [ PASS ] it isOddVal xs
121159
end 
160+
begin revPartition
161+
[ TEST ] it isOdd [] [ PASS ] it isOdd []
162+
[ TEST ] it isOdd xs [ PASS ] it isOdd xs
163+
end 
122164
begin partition
123165
[ TEST ] it isOdd [] [ PASS ] it isOdd []
124166
[ TEST ] it isOdd xs [ PASS ] it isOdd xs
@@ -129,6 +171,26 @@
129171
[ TEST ] it generates [0..2] [ PASS ] it generates [0..2]
130172
[ TEST ] it generates [0..3] [ PASS ] it generates [0..3]
131173
end 
174+
begin max
175+
[ TEST ] it max [0] = 0 [ PASS ] it max [0] = 0
176+
[ TEST ] it max [1] = 1 [ PASS ] it max [1] = 1
177+
[ TEST ] it max [0,1] = 1 [ PASS ] it max [0,1] = 1
178+
[ TEST ] it max [1,0] = 1 [ PASS ] it max [1,0] = 1
179+
[ TEST ] it max [0,0] = 0 [ PASS ] it max [0,0] = 0
180+
[ TEST ] it max [1,0,0] = 1 [ PASS ] it max [1,0,0] = 1
181+
[ TEST ] it max [1,0,2] = 2 [ PASS ] it max [1,0,2] = 2
182+
[ TEST ] it max [1,3,0,2] = 3 [ PASS ] it max [1,3,0,2] = 3
183+
end 
184+
begin min
185+
[ TEST ] it min [0] = 0 [ PASS ] it min [0] = 0
186+
[ TEST ] it min [1] = 0 [ PASS ] it min [1] = 0
187+
[ TEST ] it min [0,1] = 0 [ PASS ] it min [0,1] = 0
188+
[ TEST ] it min [1,0] = 0 [ PASS ] it min [1,0] = 0
189+
[ TEST ] it min [2,2] = 2 [ PASS ] it min [2,2] = 2
190+
[ TEST ] it min [1,0,0] = 0 [ PASS ] it min [1,0,0] = 0
191+
[ TEST ] it min [1,0,2] = 0 [ PASS ] it min [1,0,2] = 0
192+
[ TEST ] it min [4,3,4,2] = 2 [ PASS ] it min [4,3,4,2] = 2
193+
end 
132194
begin sort
133195
[ TEST ] it sorts [] [ PASS ] it sorts []
134196
[ TEST ] it sorts [0] [ PASS ] it sorts [0]
@@ -143,6 +205,6 @@
143205
end 
144206
end 
145207

146-
Total: 101
147-
Passes: 101
208+
Total: 149
209+
Passes: 149
148210
>>> Main thread finished with value: true@{}%{}

tests/lib/List.nocolor.golden

Lines changed: 0 additions & 133 deletions
This file was deleted.

0 commit comments

Comments
 (0)