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}}== |