Monads/List monad: Difference between revisions

Content added Content deleted
No edit summary
Line 692: Line 692:


<pre>[[3, 4, 5], [5, 12, 13], [6, 8, 10], [7, 24, 25], [8, 15, 17], [9, 12, 15], [12, 16, 20], [15, 20, 25]]</pre>
<pre>[[3, 4, 5], [5, 12, 13], [6, 8, 10], [7, 24, 25], [8, 15, 17], [9, 12, 15], [12, 16, 20], [15, 20, 25]]</pre>

=={{header|jq}}==
{{works with|jq}}
''Also works with gojq and fq'' modulo the proviso about "::"

In this entry, we adopt the approach described in the Wikipedia article on monads
at [https://en.wikipedia.org/wiki/Monad_(functional_programming)], specifically:
<pre>
"A monad can be created by defining a type constructor M and two operations:

return :: a -> M a (often also called unit), which receives a value of type a and wraps it into a monadic value of type M a,
and
bind :: (M a) -> (a -> M b) -> (M b)
which receives a function f over type a and can transform monadic values m a applying f to the unwrapped value a,
returning a monadic value M b"
</pre>

In the following, the monadic type `a` can be specified as any JSON
value, but for the List monad, it is just "List". Choosing a string has the advantage
that we can use jq's support for function names of the form
`Namespace::identifier` to give convenient names to the "return" and
"bind" functions for the List monad, namely `List::return` and
`List::bind`.

Since gojq does not currently support the definition of functions
with a Namespace prefix, the following would have to be adapted; one
possibility wold be to replace occurrences of `::` in function names
by `__`.

Notice that the "return" and "bind" wrappers for List (i.e., `List::return` and
`List::bind`) can be tailored to the List monad independently of the
wrapper definitions for other monads.
<syntaxhighlight lang=jq>
# Constructor:
def Monad($type; $value):
{class: "Monad", $type, $value};

# Is the input a monad of type $Type?
def is_monad($Type):
(type == "object")
and (.class == "Monad")
and (.type == $Type) ;

# input: a value consistent with the "List" monadic type (in practice, a JSON array)
# No checking is done here as the monadic type system is outside the scope of this entry.
def List::return:
Monad("List"; .);
def List::bind(f):
if is_monad("List")
then .value |= f
else error("List::bind error: monadic type of input is \(.type)")
end;

# Two illustrative operations on JSON arrays
def increment: map(. + 1);
def double: map(. * 2);
def ml1:
[3, 4, 5] | List::return;
def ml2:
ml1 | List::bind(increment) | List::bind(double);

"\(ml1.value) -> \(ml2.value)"
</syntaxhighlight>
{{output}}
<pre>
[3,4,5] -> [8,10,12]
</pre>



=={{header|Julia}}==
=={{header|Julia}}==