algo.monads

:when clause in domonad relies on optional m-zero monad operation

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

In add-monad-step, the :when clause is implemented by this line:

(identical? bform :when)  `(if ~expr ~mexpr ~'m-zero)

which makes sense, except that m-zero is an optional operation for monads.
If :when is used with a monad that does not provide an m-zero operation,
the result (in cases where the condition evaluates to false) is an incorrect monadic value,
and strange, difficult-to-understand errors result.

I don't know that it's possible to make this work reasonably for all monads,
but at the very least the limitation should be documented, and ideally the use of :when
with a monad that does not define m-zero should issue a warning with a recommendation that
{:if :then :else} should be used instead.d

Activity

Hide
Glenn Vanderburg added a comment -

After more thinking, I think the best behavior would be to evaluate to m-zero if it's defined, and (m-result nil) otherwise. The behavior of :when is too useful with the state monad, and too cumbersome to duplicate with :if :then :else, to simply document the issue. The standard Clojure when macro evaluates to nil if the condition is false.

Show
Glenn Vanderburg added a comment - After more thinking, I think the best behavior would be to evaluate to m-zero if it's defined, and (m-result nil) otherwise. The behavior of :when is too useful with the state monad, and too cumbersome to duplicate with :if :then :else, to simply document the issue. The standard Clojure when macro evaluates to nil if the condition is false.
Hide
Konrad Hinsen added a comment -

The docstring for domonad clearly says that :when requires a definition of m-zero. I am not in favor of removing this rule, which has a clear role in the monad framework. "No value" is not in general the same as "a value of nil", so substituting (m-result nil) as a default for m-zero doesn't look like a good idea.

A better error message would indeed be desirable but I see no obvious implementation, because of the possibility of generic domonad forms for which the monad is specified later. As a workaround, I have replaced the ::undefined value by more descriptive symbols that convey a useful message to the reader:
https://github.com/clojure/algo.monads/commit/8b04e7b0bc9e70d27a497c4ce3bdb5cad37d7a1d

Show
Konrad Hinsen added a comment - The docstring for domonad clearly says that :when requires a definition of m-zero. I am not in favor of removing this rule, which has a clear role in the monad framework. "No value" is not in general the same as "a value of nil", so substituting (m-result nil) as a default for m-zero doesn't look like a good idea. A better error message would indeed be desirable but I see no obvious implementation, because of the possibility of generic domonad forms for which the monad is specified later. As a workaround, I have replaced the ::undefined value by more descriptive symbols that convey a useful message to the reader: https://github.com/clojure/algo.monads/commit/8b04e7b0bc9e70d27a497c4ce3bdb5cad37d7a1d

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: