Conversation
Greptile SummaryThis PR adds
Confidence Score: 4/5Safe to merge after adding return-value validation in There is one P1 correctness issue: the return value of
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["either-flat-map f either"] --> B{"check-either either"}
B -- "not Either" --> C["type-error"]
B -- "OK" --> D{"procedure? f"}
D -- "not procedure" --> E["type-error"]
D -- "OK" --> F{"either-right? either"}
F -- "Left" --> G["return either unchanged"]
F -- "Right" --> H["result = f (to-right either)"]
H --> I{"⚠️ check-either result\n(currently missing)"}
I -- "not Either" --> J["type-error (proposed)"]
I -- "Either" --> K["return result"]
Reviews (1): Last reviewed commit: "[210_5] 实现 either-flat-map" | Re-trigger Greptile |
| (if (either-right? either) | ||
| (f (to-right either)) | ||
| either | ||
| ) ;if |
There was a problem hiding this comment.
Return value of
f not validated
either-flat-map is a monadic bind — f is expected to return an Either. If a caller passes a plain-value function (e.g. (lambda (x) (* x 2))), the result is silently a non-Either, breaking the type invariant for every downstream either-* call. The error then surfaces with a confusing message in the downstream function rather than here.
Contrast with either-map, which wraps f's result in from-right unconditionally. For flat-map the wrapping is intentionally skipped, so an explicit runtime check is needed instead:
(if (either-right? either)
(let ((result (f (to-right either))))
(check-either result "either-flat-map: return value of f must be an Either")
result)
either
) ;if| (let* ((val1 (from-right 10)) | ||
| (val2 (either-flat-map (lambda (x) (from-right (+ x 5))) val1)) | ||
| (val3 (either-flat-map (lambda (x) (from-right (* x 2))) val2))) | ||
| (check-true (either-right? val3)) | ||
| (check (to-right val3) => 30) | ||
| ) ;let* |
There was a problem hiding this comment.
Missing short-circuit chaining test
The existing chaining test only covers Right → Right → Right. The key monadic property is that once a step returns Left, all subsequent flat-map calls must pass it through untouched. Adding a test like:
;; Right -> Left -> (short-circuit) -> Left
(let* ((val1 (from-right 7))
(val2 (either-flat-map (lambda (x) (from-left "err")) val1))
(val3 (either-flat-map (lambda (x) (from-right (* x 2))) val2)))
(check-true (either-left? val3))
(check (to-left val3) => "err")
) ;let*would explicitly verify the short-circuit behaviour that is the defining feature of monadic chaining.
No description provided.