(1) MAYBE-REF and EITHER-REF should call FAILURE and SUCCESS in tail context.
(2) In EITHER-REF, it should be an error if the default value of
FAILURE is invoked and the Left payload consists of zero or more than
one value. (This allows the implementation to do what is currently in
the spec, but it shouldn't be mandated because it somehow muddies the
idea multiple values. In a Scheme where the RAISE procedure is
multiple-values-aware and can thus take more than one value or zero
values, RAISE should be applied to the Left payload without a change,
which the current spec wouldn't allow.)
Lefts now contain exactly one value. Where a Nothing has to be changed into a Left, there is an *obj* argument.
default value of INNER-CONSTRUCTOR should be the VALUES procedure
(making it an error of a payload has more than one or zero values),
the default value of OUTER-CONSTRUCTOR should be the LIST procedure.
The default value of MAPPER should be `map'.
Here is the new definition of the sequence procedures (which correspond to
(maybe-sequence traversable map aggregator)
(either-sequence traversable map aggregator)
<p>The purpose of these procedures is to transform a
collection of Justs/Eithers of some particular type into a Just/Either
of a collection, usually of the same type.</p>
<p>The <em>aggregator</em> function is applied to the values of each
element of <em>traversable</em> in turn, and <em>map</em> is used to
construct the new traversable. If all the elements are Just/Right,
the new traversable is wrapped in a Just/Right and returned.</p>
<p>For example, a list of Justs becomes a Just list of lists if
if the map procedure is <code>map</code> and the aggregator is <code>list</code>.
In the same way, a vector of Rights containing one value each becomes
a Right vector if the map procedure is <code>vector-map</code>
and the aggregator is <code>identity</code>.</p>
<p>But if any of the elements are Nothing/Left, the first such element
is returned immediately.</p>
So the appropriate default for map depends on the type of traversable.
I agree that aggregator can safely default to `list`.
(4) The type of an object of name `mapper' should be listed in the
(5) How would the sequence operations look for a general monad?
Much the same, unless we also have a general Traversable type class.
(6) In LIST->MAYBE and LIST->EITHER the idea behind multiple values is
muddied. A Just with no values is in no way a Nothing. To preserve
these procedures for Maybes/Eithers with single-valued payloads, I
would strongly suggest making it an error if the LIST argument
contains more than one value or, in case of MAYBE->LIST, if MAYBE is a
Just containing not a single value. I am not yet sure what to do with
the procedure EITHER->LIST (also in view of EITHER->MAYBE).
I think the Right Thing is to keep these procedures as defined, but
make it clear that these procedures are non-monadic in nature; they
simply convert between a list of values and the containers.
Note that these arguments discard type information.
(7) Please add versions of LIST->MAYBE and LIST->EITHER and vice versa
that are multiple-values aware. These versions would return #f in the
Nothing case. Here we are making use of the fact that in Scheme the
empty list is not #f, so we are not confusing a Just with no value
with a Nothing.
I prefer the above approach of transforming the container values to and from a list.
This makes list->just and list->right equivalent to just and right except
for accepting a single list argument instead of multiple values.
There is no need for list->nothing or list->left.
(8) If we allow MAYBE->EOF to be called on a Just without a single
value, for symmetry, EOF->MAYBE should take more than one value. The
same goes for LISP->MAYBE. However, I would rather make it an error to
use MAYBE->LISP and MAYBE->EOF in the multiple values case.
Agreed. These procedures really shouldn't have been extended to multiple values, and I'm reverting all of them.
(11) MAYBE-UNFOLD and EITHER-UNFOLD should take more than one value for SEED.
This is not practical given that Lefts are now only allowed to contain a single value.
(12) MAYBE-IF shouldn't have to signal an error. This is not R6RS.
The main purpose of maybe-if is to promote type safety. We want to make sure that if the value returned by the if-expression is not a Maybe that neither branch is taken. An exception is the simplest way to be sure of that.