git.iko.soy/rowtype-yoga/purescript-yoga-om-layer
on main help sign in
Add compile-fail tests for type-level safety
5f4234fMark
.spec-results+32−32
@@ -2,224 +2,224 @@
2 [
2 [
3 "Automatic Memoization builds the same layer only once when used in two branches",
3 "Automatic Memoization builds the same layer only once when used in two branches",
4 {
4 {
5− "timestamp": "1771027873496.0",
5+ "timestamp": "1771054731416.0",
6 "success": true
6 "success": true
7 }
7 }
8 ],
8 ],
9 [
9 [
10 "Automatic Memoization memoized bracketLayer acquires and releases only once",
10 "Automatic Memoization memoized bracketLayer acquires and releases only once",
11 {
11 {
12− "timestamp": "1771027873496.0",
12+ "timestamp": "1771054731416.0",
13 "success": true
13 "success": true
14 }
14 }
15 ],
15 ],
16 [
16 [
17 "Automatic Memoization memoized scoped layer runs finalizer only once",
17 "Automatic Memoization memoized scoped layer runs finalizer only once",
18 {
18 {
19− "timestamp": "1771027873496.0",
19+ "timestamp": "1771054731416.0",
20 "success": true
20 "success": true
21 }
21 }
22 ],
22 ],
23 [
23 [
24 "Composition proves Row.Nub deduplicates shared requirements at type level",
24 "Composition proves Row.Nub deduplicates shared requirements at type level",
25 {
25 {
26− "timestamp": "1771027873496.0",
26+ "timestamp": "1771054731416.0",
27 "success": true
27 "success": true
28 }
28 }
29 ],
29 ],
30 [
30 [
31 "Composition proves deduplication at runtime via shared Ref",
31 "Composition proves deduplication at runtime via shared Ref",
32 {
32 {
33− "timestamp": "1771027873496.0",
33+ "timestamp": "1771054731416.0",
34 "success": true
34 "success": true
35 }
35 }
36 ],
36 ],
37 [
37 [
38 "Error Channel composes layers with different error types",
38 "Error Channel composes layers with different error types",
39 {
39 {
40− "timestamp": "1771027873496.0",
40+ "timestamp": "1771054731416.0",
41 "success": true
41 "success": true
42 }
42 }
43 ],
43 ],
44 [
44 [
45 "Error Channel propagates errors from the first layer",
45 "Error Channel propagates errors from the first layer",
46 {
46 {
47− "timestamp": "1771027873496.0",
47+ "timestamp": "1771054731416.0",
48 "success": true
48 "success": true
49 }
49 }
50 ],
50 ],
51 [
51 [
52 "Error Channel propagates errors from the second layer",
52 "Error Channel propagates errors from the second layer",
53 {
53 {
54− "timestamp": "1771027873496.0",
54+ "timestamp": "1771054731416.0",
55 "success": true
55 "success": true
56 }
56 }
57 ],
57 ],
58 [
58 [
59 "Error Channel propagates errors through vertical composition",
59 "Error Channel propagates errors through vertical composition",
60 {
60 {
61− "timestamp": "1771027873496.0",
61+ "timestamp": "1771054731416.0",
62 "success": true
62 "success": true
63 }
63 }
64 ],
64 ],
65 [
65 [
66 "Error Channel scoped layer error triggers finalizers",
66 "Error Channel scoped layer error triggers finalizers",
67 {
67 {
68− "timestamp": "1771027873496.0",
68+ "timestamp": "1771054731416.0",
69 "success": true
69 "success": true
70 }
70 }
71 ],
71 ],
72 [
72 [
73 "Error Channel scoped layers with errors run via runScopedWith",
73 "Error Channel scoped layers with errors run via runScopedWith",
74 {
74 {
75− "timestamp": "1771027873496.0",
75+ "timestamp": "1771054731416.0",
76 "success": true
76 "success": true
77 }
77 }
78 ],
78 ],
79 [
79 [
80 "Functor / Apply / Bind applies two layers",
80 "Functor / Apply / Bind applies two layers",
81 {
81 {
82− "timestamp": "1771027873496.0",
82+ "timestamp": "1771054731416.0",
83 "success": true
83 "success": true
84 }
84 }
85 ],
85 ],
86 [
86 [
87 "Functor / Apply / Bind binds layers sequentially",
87 "Functor / Apply / Bind binds layers sequentially",
88 {
88 {
89− "timestamp": "1771027873496.0",
89+ "timestamp": "1771054731416.0",
90 "success": true
90 "success": true
91 }
91 }
92 ],
92 ],
93 [
93 [
94 "Functor / Apply / Bind maps over layer output",
94 "Functor / Apply / Bind maps over layer output",
95 {
95 {
96− "timestamp": "1771027873496.0",
96+ "timestamp": "1771054731416.0",
97 "success": true
97 "success": true
98 }
98 }
99 ],
99 ],
100 [
100 [
101 "Layer recovering does not retry on non-matching errors",
101 "Layer recovering does not retry on non-matching errors",
102 {
102 {
103− "timestamp": "1771027873496.0",
103+ "timestamp": "1771054731416.0",
104 "success": true
104 "success": true
105 }
105 }
106 ],
106 ],
107 [
107 [
108 "Layer recovering only retries the specified error in a multi-error layer",
108 "Layer recovering only retries the specified error in a multi-error layer",
109 {
109 {
110− "timestamp": "1771027873496.0",
110+ "timestamp": "1771054731416.0",
111 "success": true
111 "success": true
112 }
112 }
113 ],
113 ],
114 [
114 [
115 "Layer recovering preserves the error when retries are exhausted",
115 "Layer recovering preserves the error when retries are exhausted",
116 {
116 {
117− "timestamp": "1771027873496.0",
117+ "timestamp": "1771054731416.0",
118 "success": true
118 "success": true
119 }
119 }
120 ],
120 ],
121 [
121 [
122 "Layer recovering retries layer construction on matching errors",
122 "Layer recovering retries layer construction on matching errors",
123 {
123 {
124− "timestamp": "1771027873496.0",
124+ "timestamp": "1771054731416.0",
125 "success": true
125 "success": true
126 }
126 }
127 ],
127 ],
128 [
128 [
129 "Layer recovering uses RetryStatus in the check",
129 "Layer recovering uses RetryStatus in the check",
130 {
130 {
131− "timestamp": "1771027873496.0",
131+ "timestamp": "1771054731416.0",
132 "success": true
132 "success": true
133 }
133 }
134 ],
134 ],
135 [
135 [
136 "Layer repeating repeats layer construction while condition holds",
136 "Layer repeating repeats layer construction while condition holds",
137 {
137 {
138− "timestamp": "1771027873496.0",
138+ "timestamp": "1771054731416.0",
139 "success": true
139 "success": true
140 }
140 }
141 ],
141 ],
142 [
142 [
143 "Layer repeating stops when policy exhausted",
143 "Layer repeating stops when policy exhausted",
144 {
144 {
145− "timestamp": "1771027873496.0",
145+ "timestamp": "1771054731416.0",
146 "success": true
146 "success": true
147 }
147 }
148 ],
148 ],
149 [
149 [
150 "Parallel runs layers in parallel via parApply",
150 "Parallel runs layers in parallel via parApply",
151 {
151 {
152− "timestamp": "1771027873496.0",
152+ "timestamp": "1771054731416.0",
153 "success": true
153 "success": true
154 }
154 }
155 ],
155 ],
156 [
156 [
157 "Scoped Layers combines scoped and non-scoped layers",
157 "Scoped Layers combines scoped and non-scoped layers",
158 {
158 {
159− "timestamp": "1771027873496.0",
159+ "timestamp": "1771054731416.0",
160 "success": true
160 "success": true
161 }
161 }
162 ],
162 ],
163 [
163 [
164 "Scoped Layers fresh layer builds twice even when same base layer",
164 "Scoped Layers fresh layer builds twice even when same base layer",
165 {
165 {
166− "timestamp": "1771027873496.0",
166+ "timestamp": "1771054731416.0",
167 "success": true
167 "success": true
168 }
168 }
169 ],
169 ],
170 [
170 [
171 "Scoped Layers runs finalizers in reverse order on success",
171 "Scoped Layers runs finalizers in reverse order on success",
172 {
172 {
173− "timestamp": "1771027873496.0",
173+ "timestamp": "1771054731416.0",
174 "success": true
174 "success": true
175 }
175 }
176 ],
176 ],
177 [
177 [
178 "Scoped Layers runs finalizers when the callback throws",
178 "Scoped Layers runs finalizers when the callback throws",
179 {
179 {
180− "timestamp": "1771027873496.0",
180+ "timestamp": "1771054731416.0",
181 "success": true
181 "success": true
182 }
182 }
183 ],
183 ],
184 [
184 [
185 "Scoped Layers threads finalizers through vertical composition (provide)",
185 "Scoped Layers threads finalizers through vertical composition (provide)",
186 {
186 {
187− "timestamp": "1771027873496.0",
187+ "timestamp": "1771054731416.0",
188 "success": true
188 "success": true
189 }
189 }
190 ],
190 ],
191 [
191 [
192 "Scoped Layers works with bracketLayer",
192 "Scoped Layers works with bracketLayer",
193 {
193 {
194− "timestamp": "1771027873496.0",
194+ "timestamp": "1771054731416.0",
195 "success": true
195 "success": true
196 }
196 }
197 ],
197 ],
198 [
198 [
199 "wireLayers memoizes shared dependencies within wireLayers",
199 "wireLayers memoizes shared dependencies within wireLayers",
200 {
200 {
201− "timestamp": "1771027873496.0",
201+ "timestamp": "1771054731416.0",
202 "success": true
202 "success": true
203 }
203 }
204 ],
204 ],
205 [
205 [
206 "wireLayers wires a diamond dependency",
206 "wireLayers wires a diamond dependency",
207 {
207 {
208− "timestamp": "1771027873496.0",
208+ "timestamp": "1771054731416.0",
209 "success": true
209 "success": true
210 }
210 }
211 ],
211 ],
212 [
212 [
213 "wireLayers wires a simple linear chain (A -> B -> C)",
213 "wireLayers wires a simple linear chain (A -> B -> C)",
214 {
214 {
215− "timestamp": "1771027873496.0",
215+ "timestamp": "1771054731416.0",
216 "success": true
216 "success": true
217 }
217 }
218 ],
218 ],
219 [
219 [
220 "wireLayers wires independent layers with no inter-dependencies",
220 "wireLayers wires independent layers with no inter-dependencies",
221 {
221 {
222− "timestamp": "1771027873496.0",
222+ "timestamp": "1771054731416.0",
223 "success": true
223 "success": true
224 }
224 }
225 ]
225 ]
compile-fail-tests/CombineDuplicateProv.pursnew file+13
@@ -0,0 +1,13 @@
1+-- EXPECT: TypesDoNotUnify
2+module Yoga.Om.Layer.CompileFailTest where
3+
4+import Prelude
5+import Yoga.Om.Layer (OmLayer, Scope, makeLayer, combineRequirements, runScoped)
6+
7+layer1 :: OmLayer (scope :: Scope) () { value :: Int }
8+layer1 = makeLayer (pure { value: 1 })
9+
10+layer2 :: OmLayer (scope :: Scope) () { value :: Int }
11+layer2 = makeLayer (pure { value: 2 })
12+
13+bad = runScoped (combineRequirements layer1 layer2)
src/Yoga/Om/Layer.purs+6−6
@@ -380,7 +380,7 @@ withScopedWith handlers layer callback = bracket acquire release use
380-- =============================================================================
380-- =============================================================================
381
381
382combineRequirements
382combineRequirements
383− :: forall req1 req2 prov1 prov2 err1 err2 provMerged provMergedRaw reqMerged reqDeduped errMerged errDeduped _req1 _req2 _err1 _err2
383+ :: forall req1 req2 prov1 prov2 err1 err2 provMerged reqMerged reqDeduped errMerged errDeduped _req1 _req2 _err1 _err2
384 . Union req1 req2 reqMerged
384 . Union req1 req2 reqMerged
385 => Nub reqMerged reqDeduped
385 => Nub reqMerged reqDeduped
386 => Union req1 _req1 reqDeduped
386 => Union req1 _req1 reqDeduped
@@ -389,8 +389,8 @@ combineRequirements
389 => Nub errMerged errDeduped
389 => Nub errMerged errDeduped
390 => Union err1 _err1 errDeduped
390 => Union err1 _err1 errDeduped
391 => Union err2 _err2 errDeduped
391 => Union err2 _err2 errDeduped
392− => Union prov1 prov2 provMergedRaw
392+ => Union prov1 prov2 provMerged
393− => Nub provMergedRaw provMerged
393+ => Nub provMerged provMerged
394 => Keys req1
394 => Keys req1
395 => Keys req2
395 => Keys req2
396 => OmLayer req1 err1 (Record prov1)
396 => OmLayer req1 err1 (Record prov1)
@@ -511,9 +511,9 @@ instance
511 , Nub errMergedRaw errMerged
511 , Nub errMergedRaw errMerged
512 , Union accErr _e1 errMerged
512 , Union accErr _e1 errMerged
513 , Union nextErr _e2 errMerged
513 , Union nextErr _e2 errMerged
514− -- merge provisions
514+ -- merge provisions (Nub provMerged provMerged ensures disjoint)
515− , Union accProv nextProv provMergedRaw
515+ , Union accProv nextProv provMerged
516− , Nub provMergedRaw provMerged
516+ , Nub provMerged provMerged
517 -- recurse
517 -- recurse
518 , WireLayersRL tail layers accReq errMerged provMerged resReq resErr resProv
518 , WireLayersRL tail layers accReq errMerged provMerged resReq resErr resProv
519 ) =>
519 ) =>