[ALGOM-7] maybe-m breaks the monad laws. Created: 15/Sep/12 Updated: 05/Feb/14 Resolved: 05/Feb/14
|Reporter:||Seth J. Gold||Assignee:||Konrad Hinsen|
One of the monad laws is that (m-bind (m-result v) f) should be the same as (f v). However, this is not the case in maybe-m:
user=> (with-monad maybe-m (m-bind (m-result nil) nil?))
user=> (nil? nil)
The crux of the problem is that in algo.monad's maybe-m, there is no way to wrap a nil in a Just-like container.
|Comment by Seth J. Gold [ 15/Sep/12 3:27 PM ]|
Just realized that that demonstration doesn't actually work, because the function passed to m-bind is supposed to return a monadic value. Here's a better one:
user=> (with-monad maybe-m (m-bind (m-result nil) (comp m-result nil?)))
|Comment by Bruno Tavares [ 07/Jun/13 8:51 PM ]|
I don't think this would be a valid example.
Here is an example in Haskell
; Clojure example
;; Both examples will fail
Those errors would not be possible to happen with Haskell's type system.
The following snippet shows it evaluates properly the monadic bind law for valid operations
(let [value 1
|Comment by Konrad Hinsen [ 05/Feb/14 5:20 AM ]|
The Clojure implementation of maybe-m is based on the convention that nil is not a value, but a marker for "not a value". That's a very common convention in Clojure, so from a practical point of view this is the most useful way to implement maybe-m.
There are other options, and everyone is invited to implement their personal preference and use it in place of maybe-m. For example, a monadic value could be either an empty list or a list containing a single value.
Note that the Haskell approach of setting up a special type for the maybe-m container is not an option in a dynamically typed language. Whatever you choose to represent "no value" can be created outside of the monad and thus be used to violate the monad laws. It must be understood that the monad laws are valid only subject to the conventions of the specific monad.