Monads/List monad: Difference between revisions

m
syntax highlighting fixup automation
m (syntax highlighting fixup automation)
Line 23:
 
We can use a list monad in AppleScript to express set comprehension for the Pythagorean triples, but the lack of nestable first class (and anonymous) functions means that the closure can only be achieved using script objects, which makes the idiom rather less direct and transparent. AppleScript is creaking at the seams here.
<langsyntaxhighlight AppleScriptlang="applescript">-- MONADIC FUNCTIONS (for list monad) ------------------------------------------
 
-- Monadic bind for lists is simply ConcatMap
Line 138:
end script
end if
end mReturn</langsyntaxhighlight>
{{Out}}
<langsyntaxhighlight AppleScriptlang="applescript">{{3, 4, 5}, {5, 12, 13}, {6, 8, 10}, {7, 24, 25}, {8, 15, 17}, {9, 12, 15}, {12, 16, 20}, {15, 20, 25}}</langsyntaxhighlight>
 
=={{header|C}}==
Line 150:
Still, the task example is constrained enough that we can provide an implementation like:
 
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <stdlib.h>
 
Line 176:
int main() {
task(13);
}</langsyntaxhighlight>
 
Which, from the command line, might look like:
 
<langsyntaxhighlight lang="bash">$ ./monad
13</langsyntaxhighlight>
 
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <vector>
 
Line 291:
PrintTriples(pythagoreanTriples);
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 317:
=={{header|Clojure}}==
 
<langsyntaxhighlight lang="clojure">
(defn bind [coll f] (apply vector (mapcat f coll)))
(defn unit [val] (vector val))
Line 328:
(bind doubler)
(bind vecstr)) ; also evaluates to ["6" "8" "10"]
</syntaxhighlight>
</lang>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{Trans|Go}}
<syntaxhighlight lang="delphi">
<lang Delphi>
program List_monad;
 
Line 399:
Writeln(ml1.ToString, ' -> ', ml2.ToString);
readln;
end.</langsyntaxhighlight>
{{out}}
<pre>[ 3, 4, 5] -> [ 8, 10, 12]</pre>
=={{header|EchoLisp}}==
Our monadic lists will take the form (List a b c ...), ie raw lists prefixed by the List symbol.
<langsyntaxhighlight lang="scheme">
;; -> and ->> are the pipeline operators
;; (-> x f g h) = (h (g ( f x)))
Line 424:
(-> '(1 -2 3 -5) List.unit (List.bind List.cube) (List.bind List.tostr))
→ (List "1" "-8" "27" "-125")
</syntaxhighlight>
</lang>
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
type ListMonad() =
member o.Bind( (m:'a list), (f: 'a -> 'b list) ) = List.concat( List.map f m )
Line 441:
printf "%A" (pyth_triples 100)
</syntaxhighlight>
</lang>
 
The list monad is equivalent to [[List comprehensions]] which are built into F#:
 
<langsyntaxhighlight lang="fsharp">
// Monads/List monad . Nigel Galloway: March 8th., 2021
List.iter ((+) 1>>(*) 2>>printf "%d ") [3;4;5]; printfn "";;
Line 455:
let test n=match valid(Ok n) with Ok g->printfn "%d is valid" g|Error e->printfn "Error: %d %s" n e
[5..10]|>List.iter test
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 470:
=={{header|Factor}}==
Factor comes with an implementation of Haskell-style monads in the <code>monads</code> vocabulary.
<langsyntaxhighlight lang="factor">USING: kernel math monads prettyprint ;
FROM: monads => do ;
 
{ 3 4 5 }
>>= [ 1 + array-monad return ] swap call
>>= [ 2 * array-monad return ] swap call .</langsyntaxhighlight>
Or:
<langsyntaxhighlight lang="factor">{ 3 4 5 }
[ 1 + array-monad return ] bind
[ 2 * array-monad return ] bind .</langsyntaxhighlight>
Or:
<langsyntaxhighlight lang="factor">{
[ { 3 4 5 } ]
[ 1 + array-monad return ]
[ 2 * array-monad return ]
} do .</langsyntaxhighlight>
{{out}}
<pre>
Line 494:
=={{header|FreeBASIC}}==
{{trans|Ring}}
<langsyntaxhighlight lang="freebasic">Dim As Integer m1(1 To 3) = {3,4,5}
Dim As String m2 = "["
Dim As Integer x, y ,z
Line 505:
m2 &= "]"
Print m2
Sleep</langsyntaxhighlight>
{{out}}
<pre>[8, 10, 12]</pre>
Line 511:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 545:
ml2 := ml1.bind(increment).bind(double)
fmt.Printf("%v -> %v\n", ml1.value, ml2.value)
}</langsyntaxhighlight>
 
{{out}}
Line 555:
 
Haskell has the built-in <code>Monad</code> type class, and the built-in list type already conforms to the <code>Monad</code> type class.
<langsyntaxhighlight lang="haskell">main = print $ [3,4,5] >>= (return . (+1)) >>= (return . (*2)) -- prints [8,10,12]</langsyntaxhighlight>
 
Or, written using <code>do</code> notation:
<langsyntaxhighlight lang="haskell">main = print $ do x <- [3,4,5]
y <- return (x+1)
z <- return (y*2)
return z</langsyntaxhighlight>
 
Or alternately:
<langsyntaxhighlight lang="haskell">main = print $ do x <- [3,4,5]
let y = x+1
let z = y*2
return z</langsyntaxhighlight>
 
Using the list monad to express set comprehension for Pythagorean triples:
<langsyntaxhighlight lang="haskell">pythagoreanTriples :: Integer -> [(Integer, Integer, Integer)]
pythagoreanTriples n =
[1 .. n] >>= (\x ->
Line 577:
if x^2 + y^2 == z^2 then return (x,y,z) else [])))
 
main = print $ pythagoreanTriples 25</langsyntaxhighlight>
{{out}}
<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>
 
Which can be written using <code>do</code> notation:
<langsyntaxhighlight lang="haskell">pythagoreanTriples :: Integer -> [(Integer, Integer, Integer)]
pythagoreanTriples n = do x <- [1 .. n]
y <- [x+1 .. n]
z <- [y+1 .. n]
if x^2 + y^2 == z^2 then return (x,y,z) else []</langsyntaxhighlight>
 
Or directly as a list comprehension:
<langsyntaxhighlight lang="haskell">pythagoreanTriples :: Integer -> [(Integer, Integer, Integer)]
pythagoreanTriples n = [(x,y,z) | x <- [1 .. n], y <- [x+1 .. n], z <- [y+1 .. n], x^2 + y^2 == z^2]</langsyntaxhighlight>
 
=={{header|J}}==
Line 598:
That said, here is an implementation which might be adequate for the current task description:
 
<langsyntaxhighlight Jlang="j">bind=: S:0
unit=: boxopen
 
m_num=: unit
m_str=: unit@":</langsyntaxhighlight>
 
Task example:
 
<langsyntaxhighlight Jlang="j"> m_str bind m_num 5
┌─┐
│5│
└─┘</langsyntaxhighlight>
 
=={{header|Javascript}}==
 
<langsyntaxhighlight lang="javascript">
Array.prototype.bind = function (func) {
return this.map(func).reduce(function (acc, a) { return acc.concat(a); });
Line 632:
 
[3,4,5].bind(listy_inc).bind(listy_doub); // [8, 10, 12]
</syntaxhighlight>
</lang>
 
 
ES5 Example: Using the list monad to express set comprehension
 
<langsyntaxhighlight JavaScriptlang="javascript">(function (n) {
 
// ENCODING A SET COMPREHENSION IN TERMS OF A LIST MONAD
Line 687:
}
 
})(25);</langsyntaxhighlight>
 
{{Out}}
Line 696:
Julia uses the function bind for binding a channel to a task, but this can be imported and overloaded.
The |> syntax in Julia can also be used to chain functions taking one argument.
<langsyntaxhighlight lang="julia">julia> unit(v) = [v...]
unit (generic function with 1 method)
 
Line 721:
8
10
</syntaxhighlight>
</lang>
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.2.10
 
class MList<T : Any> private constructor(val value: List<T>) {
Line 742:
val fv = iv.bind(::doubler).bind(::letters)
println(fv.value)
}</langsyntaxhighlight>
 
{{out}}
Line 750:
=={{header|Nim}}==
a natural use of a list-wrapped return value is when there can be more than one result from a function, for example square roots have a positive and negative solution, and the inverse sine function has multiple solutions we might be interested in.
<langsyntaxhighlight lang="nim">import math,sequtils,sugar,strformat
func root(x:float):seq[float] = @[sqrt(x),-sqrt(x)]
func asin(x:float):seq[float] = @[arcsin(x),arcsin(x)+TAU,arcsin(x)-TAU]
Line 760:
input.map(f).concat
 
echo [0.5] --> root --> asin --> format </langsyntaxhighlight>
{{out}}<pre>@["0.79", "7.07", "-5.50", "-0.79", "5.50", "-7.07"]</pre>
 
=={{header|OCaml}}==
Defining the list monad is fairly straightforward:
<langsyntaxhighlight lang="ocaml">let bind : 'a list -> ('a -> 'b list) -> 'b list =
fun l f -> List.flatten (List.map f l)
 
let return x = [x]</langsyntaxhighlight>
 
For convenience, the example will also use the following definitions:
<langsyntaxhighlight lang="ocaml">let (>>) = bind (* operator for inline binding *)
let (let*) = bind (* let pruning for easy bind *)
 
let print_str_list l =
Format.printf "[%a]" (fun fmt -> Format.pp_print_list Format.pp_print_string fmt) l</langsyntaxhighlight>
 
First example: increment and print
<langsyntaxhighlight lang="ocaml">let incr x = return (x+1)
let hex x = return (Format.sprintf "%#x" x)
 
Line 796:
let* x = List.init 5 (fun x -> x) in
let* y = incr x in hex y
in print_str_list l</langsyntaxhighlight>
 
Second example: pythegorean triplets
<langsyntaxhighlight lang="ocaml">(* Version 1 : with explicit calls *)
let pythegorean_triple n =
let x = List.init n (fun x -> x) in
Line 822:
let* y = List.init n (fun x -> x) in
let* z = List.init n (fun x -> x) in
if x*x + y*y = z*z then return (x,y,z) else []</langsyntaxhighlight>
 
=={{header|Perl}}==
With the help of the CPAN module <code>Data::Monad</code>, we can work with list monads.
<langsyntaxhighlight lang="perl">use strict;
use feature 'say';
use Data::Monad::List;
Line 853:
for (@{shift @triples}) {
say keys %$_ if keys %$_;
}</langsyntaxhighlight>
{{out}}
<pre>000
Line 869:
=={{header|Phix}}==
{{trans|Go}}
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">function</span> <span style="color: #000000;">bindf</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
Line 889:
<span style="color: #000000;">m2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">bindf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bindf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">increment</span><span style="color: #0000FF;">),</span><span style="color: #000000;">double</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%v -&gt; %v\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">m1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">m2</span><span style="color: #0000FF;">})</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 897:
=={{header|Python}}==
 
<langsyntaxhighlight lang="python">"""A List Monad. Requires Python >= 3.7 for type hints."""
from __future__ import annotations
from itertools import chain
Line 957:
)
)
</syntaxhighlight>
</lang>
 
{{out}}
Line 975:
Note that this also demonstrates how to use Racket's macro system to implement the do syntax.
 
<langsyntaxhighlight lang="racket">#lang racket
 
(define (bind x f) (append-map f x))
Line 1,017:
 
(pythagorean-triples* 25)
;; => '((3 4 5) (5 12 13) (6 8 10) (8 15 17) (9 12 15) (12 16 20))</langsyntaxhighlight>
 
=== With functional package ===
Line 1,023:
The [https://docs.racket-lang.org/functional/interfaces.html functional] package has already implemented the list monad.
 
<langsyntaxhighlight lang="racket">#lang racket
 
(require data/monad
Line 1,038:
 
(pythagorean-triples 25)
;; => '((3 4 5) (5 12 13) (6 8 10) (8 15 17) (9 12 15) (12 16 20))</langsyntaxhighlight>
 
=={{header|Raku}}==
Line 1,049:
 
The * in the bind blocks are typically referred to as "whatever"; whatever + 3 etc. The guillemot (») is the hyper operator; descend into the data structure and apply the following operator/function to each member.
<syntaxhighlight lang="raku" perl6line>multi bind (@list, &code) { @list.map: &code };
 
multi bind ($item, &code) { $item.&code };
Line 1,055:
sub divisors (Int $int) { gather for 1 .. $int { .take if $int %% $_ } }
 
put (^10).&bind(* + 3).&bind(&divisors)».&bind(*.base: 2).join: "\n";</langsyntaxhighlight>
 
{{out}}
Line 1,070:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Monads/List monad
 
Line 1,083:
str = str + "]"
see str + nl
</syntaxhighlight>
</lang>
Output:
<pre>
Line 1,091:
=={{header|Ruby}}==
 
<langsyntaxhighlight lang="ruby">
class Array
def bind(f)
Line 1,135:
 
[3,4,5].bind_comp(listy_doub, listy_inc) #=> [8, 10, 12]
</syntaxhighlight>
</lang>
 
=={{header|uBasic/4tH}}==
{{trans|Ring}}
<syntaxhighlight lang="text">s := "[" : Push 5, 4, 3
 
Do While Used ()
Line 1,147:
 
Print Show (Set (s, Join (Clip (s, 2), "]")))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,157:
=={{header|Wren}}==
{{trans|Go}}
<langsyntaxhighlight lang="ecmascript">class Mlist {
construct new(value) { _value = value }
 
Line 1,179:
var ml1 = Mlist.unit([3, 4, 5])
var ml2 = ml1.bind(increment).bind(double)
System.print("%(ml1.value) -> %(ml2.value)")</langsyntaxhighlight>
 
{{out}}
Line 1,191:
{{trans|Ruby}}
Here we create a class to do Monad like things. Unlike Ruby, we can't augment the baked in List/Array object so this more verbose. Also unlike Ruby, we can directly compose as we are applying the composition to each element (vs the list-as-object).
<langsyntaxhighlight lang="zkl">class MList{
fcn init(xs){ var list=vm.arglist }
fcn bind(f) { list=list.apply(f); self }
fcn toString{ list.toString() }
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">inc:=Op("+",1); // '+(1)
str:="toString";
MList(3,4,5).bind(inc).bind(str).println(" == (4,5,6)");
Line 1,204:
 
comp:=Utils.Helpers.fcomp; // comp(f,g) == f.g == f(g(x))
MList(3,4,5).bind(comp(doub,inc)).println(" == (8,10,12)");</langsyntaxhighlight>
{{out}}
<pre>
10,327

edits