Add preconditions to -mbind implementations
yurrriq opened this issue · 9 comments
iirc protocol method implementations can't have :pre
conditions, but a simple if
that throws an error upon encountering a context mismatch should suffice.
What do you @yurrriq think about this:
(require '[cats.context :as ctx] :reload)
(require '[cats.core :as m] :reload)
(require '[cats.monad.either :refer [left right]])
(require '[cats.monad.maybe :refer [just nothing]])
(m/mlet [a (just 1) b (right 2)] (m/return (+ a b)))
;; => #<Just 3>
(alter-var-root #'ctx/*strict* (constantly true))
;; => true
(m/mlet [a (just 1) b (right 2)] (m/return (+ a b)))
;; => IllegalArgumentException Context mismatch: you can't mix different context. cats.context/throw-illegal-argument (context.cljc:33)
It not yet finished (not in master) because I need some fixes before but is a generic approach instead of having assert on each -mbind impl. It just checks if the previously set context is equal to the current provided one and if they mismatches, then the exception is raised if strict mode is enabled.
I think the first example should always fail. The check and error message seem solid, though. What else does strict mode do?
Just that, it disallows overwrite the already set context and checks if the contexts are different and just throws an exception. In any case I agree with you and I will add asserts independently of the strict mode.
(m/mlet [a (just 1) b (right 2)] (m/return (+ a b)))
;; AssertionError Assert failed: Context mismatch: #<Right 2> is not allowed to use with maybe context.
This seems like a much better error message and works as is, without strict mode.
Looks good to me.
Nice, this is already in master ;)