Monads/Writer monad: Difference between revisions

Added FreeBASIC
(Added FreeBASIC)
 
(38 intermediate revisions by 16 users not shown)
Line 1:
{{draft task}}
[[Category:Monads]]
 
Line 11:
# Apply a composition of the Writer versions of root, addOne, and half to the integer 5, deriving both a value for the Golden Ratio φ, and a concatenated log of the function applications (starting with the initial value, and followed by the application of root, etc.)
 
=={{header|ALGOL 68}}==
{{Trans|Go}}
<syntaxhighlight lang="algol68">BEGIN
MODE MWRITER = STRUCT( LONG REAL value
, STRING log
);
PRIO BIND = 9;
OP BIND = ( MWRITER m, PROC( LONG REAL )MWRITER f )MWRITER:
( MWRITER n := f( value OF m );
log OF n := log OF m + log OF n;
n
);
 
OP LEN = ( STRING s )INT: ( UPB s + 1 ) - LWB s;
PRIO PAD = 9;
OP PAD = ( STRING s, INT width )STRING: IF LEN s >= width THEN s ELSE s + ( width - LEN s ) * " " FI;
 
PROC unit = ( LONG REAL v, STRING s )MWRITER: ( v, " " + s PAD 17 + ":" + fixed( v, -19, 15 ) + REPR 10 );
PROC root = ( LONG REAL v )MWRITER: unit( long sqrt( v ), "Took square root" );
PROC add one = ( LONG REAL v )MWRITER: unit( v+1, "Added one" );
PROC half = ( LONG REAL v )MWRITER: unit( v/2, "Divided by two" );
MWRITER mw2 := unit( 5, "Initial value" ) BIND root BIND add one BIND half;
print( ( "The Golden Ratio is", fixed( value OF mw2, -19, 15 ), newline ) );
print( ( newline, "This was derived as follows:-", newline ) );
print( ( log OF mw2 ) )
END</syntaxhighlight>
{{out}}
<pre>
The Golden Ratio is 1.618033988749895
 
This was derived as follows:-
Initial value : 5.000000000000000
Took square root : 2.236067977499790
Added one : 3.236067977499790
Divided by two : 1.618033988749895
</pre>
 
=={{header|AppleScript}}==
Line 20 ⟶ 58:
More than a light-weight scripting language is really likely to need, but a way of stretching it a bit, and understanding its relationship to other languages. What AppleScript mainly lacks (apart from a well-developed library, and introspective records/dictionaries which know what keys/fields they have), is a coherent type of first class (and potentially anonymous) function. To get first class objects, we have to wrap 2nd class handlers in 1st class scripts.
 
<langsyntaxhighlight AppleScriptlang="applescript">-- WRITER MONAD FOR APPLESCRIPT
 
-- How can we compose functions which take simple values as arguments
Line 138 ⟶ 176:
end call
end script
end sBind</langsyntaxhighlight>
 
{{Out}}
Line 149 ⟶ 187:
divided by two -> 1.61803398875"
}</pre>
 
=={{header|ATS}}==
The entry for [[#Haskell|Haskell]] inspired me to do such things as add a <code>&gt;=&gt;</code> operator, and to use <code>return</code> as a name for the ''unit'' operation. But notice that I write <code>return&lt;double&gt;</code>. The template system, for whatever reason, could not infer the type, if I left out the template parameter. It did not signal an error, but instead produced C code that could not be compiled. This kind of behavior is common with the Postiats implementation of ATS, and must be gotten used to.
 
(''Footnote'': Sometimes the template system will produce C code that ''can'' be compiled but does not function correctly! No doubt the template system can be made more shipshape, but it is what it is. In any case, one then goes through the code and fills in elided template parameters, until the code works.)
 
<syntaxhighlight lang="ats">
#include "share/atspre_staload.hats"
 
%{^
#include <math.h>
%}
 
#define NIL list_nil ()
#define :: list_cons
 
(* The log is a list of strings. For efficiency, it is ordered
most-recent-first. The static value "n" represents the number of
entries in the log. (It exists and is used only during the
typechecking phase.) *)
datatype Writer (a : t@ype+, n : int) =
| Writer of (a, list (string, n))
typedef Writer (a : t@ype+) = [n : int] Writer (a, n)
 
prfn
lemma_Writer_param {a : t@ype}
{n : int}
(m : Writer (a, n))
:<prf> [0 <= n] void =
let
val+ Writer (_, log) = m
in
lemma_list_param log
end
 
fn {a : t@ype}
unit_Writer (x : a) : Writer (a, 1) =
let
val msg = string_append ("unit_Writer (",
tostring_val<a> x, ")")
val msg = strptr2string msg
in
Writer (x, msg :: NIL)
end
 
overload return with unit_Writer
 
fn {a, b : t@ype}
bind_Writer {n : int}
(m : Writer (a, n),
f : a -<cloref1> Writer b)
: [n1 : int | n <= n1] Writer (b, n1) =
let
val+ Writer (x, log) = m
val y = f (x)
prval () = lemma_Writer_param y
val+ Writer (y, entries) = y
in
Writer (y, list_append (entries, log))
end
 
infixl 0 >>=
overload >>= with bind_Writer
 
fn {a, b, c : t@ype}
compose_Writer (f : a -<cloref1> Writer b,
g : b -<cloref1> Writer c)
: a -<cloref1> Writer c =
lam m => f m >>= g
 
infixl 0 >=>
overload >=> with compose_Writer
 
(* "make_Writer_closure_from_fun" wraps an ordinary function from a to
b, resulting in a closure that will produce exactly one log
entry. *)
fn {a, b : t@ype}
make_Writer_closure_from_fun (func : a -> b,
make_msg : (a, b) -<cloref1> string)
: a -<cloref1> Writer (b, 1) =
lam x =>
let
val y = func x
in
Writer (y, make_msg (x, y) :: NIL)
end
 
overload make_Writer_closure with make_Writer_closure_from_fun
 
(* A note regarding "root": interfaces to the C math library are
available, even within the Postiats distribution, but I shall
simply make a foreign function call to sqrt(3). The Postiats
prelude itself provides no (or very little) interface to libm. *)
fn root (x : double) : double = $extfcall (double, "sqrt", x)
fn addOne (x : double) : double = succ x
fn half (x : double) : double = 0.5 * x
 
fn {a, b : t@ype}
make_logging (func : a -> b,
notation : string)
: a -<cloref1> Writer (b, 1) =
let
fn
make_msg (x : a, y : b) :<cloref1> string =
let
val msg = string_append ("(", tostring_val<a> x,
" |> ", notation, ") --> ",
tostring_val<b> y)
in
strptr2string msg
end
in
make_Writer_closure<a,b> (func, make_msg)
end
 
val logging_root = make_logging<double,double> (root, "sqrt")
val logging_addOne = make_logging<double,double> (addOne, "(+ 1.0)")
val logging_half = make_logging<double,double> (half, "(0.5 *)")
 
val the_big_whatchamacallit =
logging_root >=> logging_addOne >=> logging_half
 
fn
print_log (log : List string) : void =
let
fun
loop (lst : List0 string) : void =
case+ lst of
| NIL => ()
| hd :: tl =>
begin
println! (" ", hd);
loop tl
end
 
prval () = lemma_list_param log
in
loop (list_vt2t (list_reverse log))
end
 
implement
main0 () =
let
val x = 5.0
val m = return<double> x
val+ Writer (y, log) = m >>= the_big_whatchamacallit
in
println! ("(1 + sqrt(", x : double, "))/2 = ", y : double);
println! ("log:");
print_log log
end
</syntaxhighlight>
 
{{out}}
<pre>$ patscc -std=gnu2x -g -O2 -DATS_MEMALLOC_GCBDW writer_monad_ats.dats -lgc -lm && ./a.out
(1 + sqrt(5.000000))/2 = 1.618034
log:
unit_Writer (5.000000)
(5.000000 |> sqrt) --> 2.236068
(2.236068 |> (+ 1.0)) --> 3.236068
(3.236068 |> (0.5 *)) --> 1.618034</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">#include <cmath>
#include <iostream>
#include <string>
 
using namespace std;
 
// Use a struct as the monad
struct LoggingMonad
{
double Value;
string Log;
};
 
// Use the >> operator as the bind function
auto operator>>(const LoggingMonad& monad, auto f)
{
auto result = f(monad.Value);
return LoggingMonad{result.Value, monad.Log + "\n" + result.Log};
}
 
// Define the three simple functions
auto Root = [](double x){ return sqrt(x); };
auto AddOne = [](double x){ return x + 1; };
auto Half = [](double x){ return x / 2.0; };
 
// Define a function to create writer monads from the simple functions
auto MakeWriter = [](auto f, string message)
{
return [=](double x){return LoggingMonad(f(x), message);};
};
 
// Derive writer versions of the simple functions
auto writerRoot = MakeWriter(Root, "Taking square root");
auto writerAddOne = MakeWriter(AddOne, "Adding 1");
auto writerHalf = MakeWriter(Half, "Dividing by 2");
 
 
int main()
{
// Compose the writers to compute the golden ratio
auto result = LoggingMonad{5, "Starting with 5"} >> writerRoot >> writerAddOne >> writerHalf;
cout << result.Log << "\nResult: " << result.Value;
}
</syntaxhighlight>
{{out}}
<pre>
Starting with 5
Taking square root
Adding 1
Dividing by 2
Result: 1.61803
</pre>
 
=={{header|EchoLisp}}==
Our monadic Writer elements will be pairs (string . value), where string is the log string.
 
<langsyntaxhighlight lang="scheme">
(define (Writer.unit x (log #f))
(if log (cons log x)
Line 196 ⟶ 449:
add-one → 2
half → 1
</syntaxhighlight>
</lang>
 
=={{header|FreeBASIC}}==
{{trans|Go}}
<syntaxhighlight lang="vbnet">Type mwriter
value As Double
log_ As String
End Type
 
Function Unit(v As Double, s As String) As mwriter
Dim As mwriter mw
mw.value = v
mw.log_ = " " & s & ": " & Str(v) & Chr(10)
Return mw
End Function
 
Function Root(mw As mwriter) As mwriter
mw.value = Sqr(mw.value)
mw.log_ = mw.log_ & " Took square Root: " & Str(mw.value) & Chr(10)
Return mw
End Function
 
Function addOne(mw As mwriter) As mwriter
mw.value = mw.value + 1
mw.log_ = mw.log_ & " Added one : " & Str(mw.value) & Chr(10)
Return mw
End Function
 
Function Half(mw As mwriter) As mwriter
mw.value = mw.value / 2
mw.log_ = mw.log_ & " Divided by two : " & Str(mw.value) & Chr(10)
Return mw
End Function
 
Dim As mwriter mw1
mw1 = Unit(5, "Initial value ")
mw1 = Root(mw1)
mw1 = addOne(mw1)
mw1 = Half(mw1)
Print "The Golden Ratio is "; mw1.value
Print !"\nThis was derived as follows:-"
Print mw1.log_
 
Sleep</syntaxhighlight>
{{out}}
<pre>The Golden Ratio is 1.618033988749895
 
This was derived as follows:-
Initial value : 5
Took square Root: 2.23606797749979
Added one : 3.23606797749979
Divided by two : 1.618033988749895</pre>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// Monads/Writer monad . Nigel Galloway: July 20th., 2022
type Riter<'n>=Riter of 'n * List<string>
let eval=function |Riter(n,g)->(n,g)
let compose f=function |Riter(n,g)->let n,l=eval(f n) in Riter(n,List.append g l)
let initV n=Riter(n,[sprintf "Initial Value %f" n])
let sqrt n=Riter(sqrt n,["Took square root"])
let div n g=Riter(n/g,[sprintf "Divided by %f" n])
let add n g=Riter(n+g,[sprintf "Added %f" n])
let result,log=eval((initV>>compose sqrt>>compose(add 1.0)>>compose(div 2.0))5.0)
log|>List.iter(printfn "%s")
printfn "Final value = %f" result
</syntaxhighlight>
{{out}}
<pre>
Initial Value 5.000000
Took square root
Added 1.000000
Divided by 2.000000
Final value = 0.618034
</pre>
 
=={{header|Factor}}==
Factor comes with an implementation of Haskell-style monads in the <code>monads</code> vocabulary.
{{works with|Factor|0.99 2019-10-06}}
<syntaxhighlight lang="factor">USING: kernel math math.functions monads prettyprint ;
FROM: monads => do ;
 
{
[ 5 "Started with five, " <writer> ]
[ sqrt "took square root, " <writer> ]
[ 1 + "added one, " <writer> ]
[ 2 / "divided by two." <writer> ]
} do .</syntaxhighlight>
{{out}}
<pre>
T{ writer
{ value 1.618033988749895 }
{ log
"Started with five, took square root, added one, divided by two."
}
}
</pre>
 
=={{header|Go}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 240 ⟶ 589:
fmt.Println("\nThis was derived as follows:-")
fmt.Println(mw2.log)
}</langsyntaxhighlight>
 
{{out}}
Line 258 ⟶ 607:
 
Making a logging version of functions (unfortunately, if we use the built-in writer monad we cannot get the values into the logs when binding):
<langsyntaxhighlight lang="haskell">import Control.Monad.Trans.Writer
import Control.Monad ((>=>))
 
Line 270 ⟶ 619:
halfOfAddOneOfRoot = logRoot >=> logAddOne >=> logHalf
 
main = print $ runWriter (halfOfAddOneOfRoot 5)</langsyntaxhighlight>
 
{{Out}}
Line 282 ⟶ 631:
Based on javascript implementation:
 
<langsyntaxhighlight Jlang="j">root=: %:
incr=: >:
half=: -:
Line 308 ⟶ 657:
loggingCompose=: dyad define
;(dyad def '<x`:6 loggingBind;y')/x,<loggingUnit y
)</langsyntaxhighlight>
 
Task example:
 
<langsyntaxhighlight Jlang="j"> 0{::Lhalf`Lincr`Lroot loggingCompose 5
1.61803
1{::Lhalf`Lincr`Lroot loggingCompose 5
Line 318 ⟶ 667:
obtained square root -> 2.23607
added 1 -> 3.23607
divided by 2 -> 1.61803</langsyntaxhighlight>
 
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.util.function.Function;
 
public final class MonadWriter {
 
public static void main(String[] aArgs) {
Monad<Double> initial = Monad.unit(5.0, "Initial value");
Monad<Double> result = initial.bind(MonadWriter::root).bind(MonadWriter::addOne).bind(MonadWriter::half);
System.out.println("The Golden Ratio is " + result.getValue() + System.lineSeparator());
System.out.println("This was derived as follows:" + System.lineSeparator() + result.getText());
}
private static Monad<Double> root(double aD) {
return Monad.unit(Math.sqrt(aD), "Took square root");
}
 
private static Monad<Double> addOne(double aD) {
return Monad.unit(aD + 1.0, "Added one");
}
 
private static Monad<Double> half(double aD) {
return Monad.unit(aD / 2.0, "Divided by two");
}
}
final class Monad<T> {
public static <T> Monad<T> unit(T aValue, String aText) {
return new Monad<T>(aValue, aText);
}
public Monad<T> bind(Function<T, Monad<T>> aFunction) {
Monad<T> monad = aFunction.apply(value);
monad.text = text + monad.text;
return monad;
}
public T getValue() {
return value;
}
public String getText() {
return text;
}
private Monad(T aValue, String aText) {
value = aValue;
text = String.format("%-21s%s%n", " " + aText, ": " + aValue);
}
private T value;
private String text;
}
</syntaxhighlight>
{{ out }}
<pre>
The Golden Ratio is 1.618033988749895
 
This was derived as follows:
Initial value : 5.0
Took square root : 2.23606797749979
Added one : 3.23606797749979
Divided by two : 1.618033988749895
</pre>
 
=={{header|JavaScript}}==
Line 324 ⟶ 741:
===ES5===
 
<langsyntaxhighlight JavaScriptlang="javascript">(function () {
'use strict';
 
Line 410 ⟶ 827:
 
return half_of_addOne_of_root(5);
})();</langsyntaxhighlight>
 
{{Out}}
Line 421 ⟶ 838:
divided by 2 -> 1.618033988749895"
}</pre>
 
=={{header|Jsish}}==
From Javascript ES5 entry.
 
<syntaxhighlight lang="javascript">'use strict';
 
/* writer monad, in Jsish */
function writerMonad() {
// START WITH THREE SIMPLE FUNCTIONS
// Square root of a number more than 0
function root(x) {
return Math.sqrt(x);
}
// Add 1
function addOne(x) {
return x + 1;
}
// Divide by 2
function half(x) {
return x / 2;
}
// DERIVE LOGGING VERSIONS OF EACH FUNCTION
function loggingVersion(f, strLog) {
return function (v) {
return {
value: f(v),
log: strLog
};
};
}
var log_root = loggingVersion(root, "obtained square root"),
log_addOne = loggingVersion(addOne, "added 1"),
log_half = loggingVersion(half, "divided by 2");
// UNIT/RETURN and BIND for the the WRITER MONAD
// The Unit / Return function for the Writer monad:
// 'Lifts' a raw value into the wrapped form
// a -> Writer a
function writerUnit(a) {
return {
value: a,
log: "Initial value: " + JSON.stringify(a)
};
}
// The Bind function for the Writer monad:
// applies a logging version of a function
// to the contents of a wrapped value
// and return a wrapped result (with extended log)
// Writer a -> (a -> Writer b) -> Writer b
function writerBind(w, f) {
var writerB = f(w.value),
v = writerB.value;
return {
value: v,
log: w.log + '\n' + writerB.log + ' -> ' + JSON.stringify(v)
};
}
// USING UNIT AND BIND TO COMPOSE LOGGING FUNCTIONS
// We can compose a chain of Writer functions (of any length) with a simple foldr/reduceRight
// which starts by 'lifting' the initial value into a Writer wrapping,
// and then nests function applications (working from right to left)
function logCompose(lstFunctions, value) {
return lstFunctions.reduceRight(
writerBind,
writerUnit(value)
);
}
 
var half_of_addOne_of_root = function (v) {
return logCompose(
[log_half, log_addOne, log_root], v
);
};
 
return half_of_addOne_of_root(5);
}
 
var writer = writerMonad();
;writer.value;
;writer.log;
 
/*
=!EXPECTSTART!=
writer.value ==> 1.61803398874989
writer.log ==> Initial value: 5
obtained square root -> 2.23606797749979
added 1 -> 3.23606797749979
divided by 2 -> 1.61803398874989
=!EXPECTEND!=
*/</syntaxhighlight>
 
{{out}}
<pre>prompt$ jsish -u writerMonad.jsi
[PASS] writerMonad.jsi</pre>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">struct Writer x::Real; msg::String; end
 
Base.show(io::IO, w::Writer) = print(io, w.msg, ": ", w.x)
Line 439 ⟶ 967:
 
println("$a => $b => $c")
println(bind(f2, "after plus 8", bind(f1, "after times 7", unit(3, "after intialization"))))
</lang>{{out}}
</syntaxhighlight>{{out}}
<pre>
after intialization: 3 => after intialization, after times 7: 21 => after intialization, after times 7, after plus 8: 29
after intialization, after times 7, after plus 8: 29
</pre>
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.2.10
 
import kotlin.math.sqrt
Line 475 ⟶ 1,005:
println("The Golden Ratio is ${fv.value}")
println("\nThis was derived as follows:-\n${fv.log}")
}</langsyntaxhighlight>
 
{{out}}
Line 486 ⟶ 1,016:
Added one : 3.23606797749979
Divided by two : 1.618033988749895
</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">from math import sqrt
from sugar import `=>`, `->`
 
type
WriterUnit = (float, string)
WriterBind = proc(a: WriterUnit): WriterUnit
 
proc bindWith(f: (x: float) -> float; log: string): WriterBind =
result = (a: WriterUnit) => (f(a[0]), a[1] & log)
 
func doneWith(x: int): WriterUnit =
(x.float, "")
 
var
logRoot = sqrt.bindWith "obtained square root, "
logAddOne = ((x: float) => x+1'f).bindWith "added 1, "
logHalf = ((x: float) => x/2'f).bindWith "divided by 2, "
 
echo 5.doneWith.logRoot.logAddOne.logHalf
</syntaxhighlight>
{{out}}
<pre>
(1.618033988749895, "obtained square root, added 1, divided by 2, ")
</pre>
 
=={{header|Perl}}==
{{trans|Raku}}
<syntaxhighlight lang="perl"># 20200704 added Perl programming solution
 
package Writer;
 
use strict;
use warnings;
 
sub new {
my ($class, $value, $log) = @_;
return bless [ $value => $log ], $class;
}
 
sub Bind {
my ($self, $code) = @_;
my ($value, $log) = @$self;
my $n = $code->($value);
return Writer->new( @$n[0], $log.@$n[1] );
}
 
sub Unit { Writer->new($_[0], sprintf("%-17s: %.12f\n",$_[1],$_[0])) }
 
sub root { Unit sqrt($_[0]), "Took square root" }
 
sub addOne { Unit $_[0]+1, "Added one" }
 
sub half { Unit $_[0]/2, "Divided by two" }
 
print Unit(5, "Initial value")->Bind(\&root)->Bind(\&addOne)->Bind(\&half)->[1];
</syntaxhighlight>
{{out}}
<pre>
Initial value : 5.000000000000
Took square root : 2.236067977500
Added one : 3.236067977500
Divided by two : 1.618033988750
</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">bind</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</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>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">unit</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">m</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">root</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">al</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">lg</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">al</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lg</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"took root: %f -&gt; %f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">addOne</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">al</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">lg</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">al</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lg</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"added one: %f -&gt; %f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">half</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">al</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">lg</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">al</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">2</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lg</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"halved it: %f -&gt; %f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</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;">"%f obtained by\n%s"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bind</span><span style="color: #0000FF;">({</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">},</span><span style="color: #000000;">root</span><span style="color: #0000FF;">),</span><span style="color: #000000;">addOne</span><span style="color: #0000FF;">),</span><span style="color: #000000;">half</span><span style="color: #0000FF;">))</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
1.618034 obtained by
took root: 5.000000 -> 2.236068
added one: 2.236068 -> 3.236068
halved it: 3.236068 -> 1.618034
</pre>
 
=={{header|PHP}}==
<syntaxhighlight lang="php">class WriterMonad {
 
/** @var mixed */
private $value;
/** @var string[] */
private $logs;
 
private function __construct($value, array $logs = []) {
$this->value = $value;
$this->logs = $logs;
}
 
public static function unit($value, string $log): WriterMonad {
return new WriterMonad($value, ["{$log}: {$value}"]);
}
 
public function bind(callable $mapper): WriterMonad {
$mapped = $mapper($this->value);
assert($mapped instanceof WriterMonad);
return new WriterMonad($mapped->value, [...$this->logs, ...$mapped->logs]);
}
 
public function value() {
return $this->value;
}
 
public function logs(): array {
return $this->logs;
}
}
 
$root = fn(float $i): float => sqrt($i);
$addOne = fn(float $i): float => $i + 1;
$half = fn(float $i): float => $i / 2;
 
$m = fn (callable $callback, string $log): callable => fn ($value): WriterMonad => WriterMonad::unit($callback($value), $log);
 
$result = WriterMonad::unit(5, "Initial value")
->bind($m($root, "square root"))
->bind($m($addOne, "add one"))
->bind($m($half, "half"));
 
print "The Golden Ratio is: {$result->value()}\n";
print join("\n", $result->logs());</syntaxhighlight>
 
{{out}}
<pre>
The Golden Ratio is: 1.6180339887499
Initial value: 5
square root: 2.2360679774998
add one: 3.2360679774998
half: 1.6180339887499
</pre>
 
=={{header|Python}}==
 
<syntaxhighlight lang="python">
"""A Writer Monad. Requires Python >= 3.7 for type hints."""
from __future__ import annotations
 
import functools
import math
import os
 
from typing import Callable
from typing import Generic
from typing import List
from typing import TypeVar
from typing import Union
 
 
T = TypeVar("T")
U = TypeVar("U")
 
 
class Writer(Generic[T]):
def __init__(self, value: Union[T, Writer[T]], *msgs: str):
if isinstance(value, Writer):
self.value: T = value.value
self.msgs: List[str] = value.msgs + list(msgs)
else:
self.value = value
self.msgs = list(f"{msg}: {self.value}" for msg in msgs)
 
def bind(self, func: Callable[[T], Writer[U]]) -> Writer[U]:
writer = func(self.value)
return Writer(writer, *self.msgs)
 
def __rshift__(self, func: Callable[[T], Writer[U]]) -> Writer[U]:
return self.bind(func)
 
def __str__(self):
return f"{self.value}\n{os.linesep.join(reversed(self.msgs))}"
 
def __repr__(self):
return f"Writer({self.value}, \"{', '.join(reversed(self.msgs))}\")"
 
 
def lift(func: Callable[[T], U], msg: str) -> Callable[[T], Writer[U]]:
"""Return a writer monad version of the simple function `func`."""
 
@functools.wraps(func)
def wrapped(value: T) -> Writer[U]:
return Writer(func(value), msg)
 
return wrapped
 
 
if __name__ == "__main__":
square_root = lift(math.sqrt, "square root")
 
add_one: Callable[[Union[int, float]], Writer[Union[int, float]]] = lift(
lambda x: x + 1, "add one"
)
 
half: Callable[[Union[int, float]], Writer[float]] = lift(
lambda x: x / 2, "div two"
)
 
print(Writer(5, "initial") >> square_root >> add_one >> half)
</syntaxhighlight>
 
{{out}}
<pre>
1.618033988749895
initial: 5
square root: 2.23606797749979
add one: 3.23606797749979
div two: 1.618033988749895
</pre>
 
=={{header|Raku}}==
Basic semantic borrowed from the Monads/List monad entry
{{trans|Go}}
<syntaxhighlight lang="raku" line># 20200508 Raku programming solution
 
class Writer { has Numeric $.value ; has Str $.log }
 
sub Bind (Writer \v, &code) {
my \n = v.value.&code;
Writer.new: value => n.value, log => v.log ~ n.log
};
 
sub Unit(\v, \s) { Writer.new: value=>v, log=>sprintf "%-17s: %.12f\n",s,v}
 
sub root(\v) { Unit v.sqrt, "Took square root" }
 
sub addOne(\v) { Unit v+1, "Added one" }
 
sub half(\v) { Unit v/2, "Divided by two" }
 
say Unit(5, "Initial value").&Bind(&root).&Bind(&addOne).&Bind(&half).log;</syntaxhighlight>
{{out}}
<pre>Initial value : 5.000000000000
Took square root : 2.236067977500
Added one : 3.236067977500
Divided by two : 1.618033988750
</pre>
 
=={{header|Ruby}}==
 
<syntaxhighlight lang="ruby"># 20220720 Ruby programming solution
class Writer
attr_reader :value, :log
 
def initialize(value, log = "New")
@value = value
if value.is_a? Proc
@log = log
else
@log = log + ": " + @value.to_s
end
end
 
def self.unit(value, log)
Writer.new(value, log)
end
 
def bind(mwriter)
new_value = mwriter.value.call(@value)
new_log = @log + "\n" + mwriter.log
self.class.new(new_value, new_log)
end
end
 
lam_sqrt = ->(number) { Math.sqrt(number) }
lam_add_one = ->(number) { number + 1 }
lam_half = ->(number) { number / 2.0 }
 
sqrt = Writer.unit( lam_sqrt, "Took square root")
add_one = Writer.unit( lam_add_one, "Added one")
half = Writer.unit( lam_half, "Divided by 2")
 
m1 = Writer.unit(5, "Initial value")
m2 = m1.bind(sqrt).bind(add_one).bind(half)
 
puts "The final value is #{m2.value}\n\n"
puts "This value was derived as follows:"
puts m2.log
</syntaxhighlight>
 
{{out}}
<pre>
The final value is 1.618033988749895
 
This value was derived as follows:
Initial value: 5
Took square root: 2.23606797749979
Added one: 3.23606797749979
Divided by 2: 1.618033988749895
</pre>
 
=={{header|Scheme}}==
{{works with|Gauche Scheme|0.9.12}}
{{works with|CHICKEN Scheme|5.3.0}}
 
The program is written in R7RS-small Scheme. For CHICKEN you will need the <code>r7rs</code> egg.
 
<syntaxhighlight lang="scheme">
(define-library (monad base)
(export make-monad monad? monad-identifier
monad-object monad-additional
>>= >=>)
(import (scheme base)
(scheme case-lambda))
(begin
 
(define-record-type <monad>
(make-monad identifier bind object additional)
monad?
(identifier monad-identifier)
(bind monad-bind)
(object monad-object)
(additional monad-additional))
 
(define >>=
(case-lambda
((m f) ((monad-bind m) m f))
((m f . g*) (apply >>= (cons (>>= m f) g*)))))
 
(define >=>
(case-lambda
((f g) (lambda (x) (>>= (f x) g)))
((f g . h*) (apply >=> (cons (>=> f g) h*)))))
 
)) ;; end library
 
(define-library (monad perform)
(export perform)
(import (scheme base)
(monad base))
(begin
 
(define-syntax perform
;; "do" is already one of the loop syntaxes, so I call this
;; syntax "perform" instead.
(syntax-rules (<-)
((perform (x <- action) clause clause* ...)
(>>= action (lambda (x) (perform clause clause* ...))))
((perform action)
action)
((perform action clause clause* ...)
(action (perform clause clause* ...)))))
 
)) ;; end library
 
(define-library (monad writer-monad)
(export make-writer-monad writer-monad?)
(import (scheme base)
(monad base))
(begin
 
;; The messages are a list, most recent message first, of whatever
;; data f decides to log.
(define (make-writer-monad object messages)
(define (bind m f)
(let ((ym (f (monad-object m))))
(let ((old-messages (monad-additional m))
(new-messages (monad-additional ym))
(y (monad-object ym)))
(make-monad 'writer-monad bind y
(append new-messages old-messages)))))
(unless (or (null? messages) (pair? messages))
;;
;; I do not actually test whether the list is proper, because
;; to do so would be inefficient.
;;
;; The R7RS-small test for properness of a list is called
;; "list?" (and the report says something tendentious in
;; defense of this name, but really it is simply historical
;; usage). The SRFI-1 procedure, by constrast, is called
;; "proper-list?".
;;
(error "should be a proper list" messages))
(make-monad 'writer-monad bind object messages))
 
(define (writer-monad? object)
(and (monad? object)
(eq? (monad-identifier object) 'writer-monad)))
 
)) ;; end library
 
(import (scheme base)
(scheme inexact)
(scheme write)
(monad base)
(monad perform)
(monad writer-monad))
 
(define root sqrt)
(define (addOne x) (+ x 1))
(define (half x) (/ x 2))
 
(define-syntax make-logging
(syntax-rules ()
((_ proc)
(lambda (x)
(define (make-msg x y) (list x 'proc y))
(let ((y (proc x)))
(make-writer-monad y (list (make-msg x y))))))))
 
(define logging-root (make-logging root))
(define logging-addOne (make-logging addOne))
(define logging-half (make-logging half))
 
(define (display-messages messages)
(if (writer-monad? messages)
(display-messages (monad-additional messages))
(begin
(display " messages:")
(newline)
(let loop ((lst (reverse messages)))
(when (pair? lst)
(display " ")
(write (car lst))
(newline)
(loop (cdr lst)))))))
 
(display "---------------") (newline)
(display "Using just >>=") (newline)
(display "---------------") (newline)
(define result
(>>= (make-writer-monad 5 '((new writer-monad 5)))
logging-root logging-addOne logging-half))
(display " (1 + sqrt(5))/2 = ")
(write (monad-object result)) (newline)
(display-messages result)
 
(newline)
 
(display "------------------") (newline)
(display "Using >>= and >=>") (newline)
(display "------------------") (newline)
(define result
(>>= (make-writer-monad 5 '((new writer-monad 5)))
(>=> logging-root logging-addOne logging-half)))
(display " (1 + sqrt(5))/2 = ")
(write (monad-object result)) (newline)
(display-messages result)
 
(newline)
 
(display "-----------------------") (newline)
(display "Using 'perform' syntax") (newline)
(display "-----------------------") (newline)
(define result
(perform (x <- (make-writer-monad 5 '((new writer-monad 5))))
(x <- (logging-root x))
(x <- (logging-addOne x))
(logging-half x)))
(display " (1 + sqrt(5))/2 = ")
(write (monad-object result)) (newline)
(display-messages result)
</syntaxhighlight>
 
{{out}}
Compile and run with <pre>gosh -r7 writer_monad_r7rs.scm</pre> or <pre>csc -O5 -X r7rs -R r7rs writer_monad_r7rs.scm && ./writer_monad_r7rs</pre>
 
(I use the high optimization level <code>-O5</code> to check I have done nothing to impede such optimization.)
 
The result is computed in three different notations. The <code>perform</code> syntax is something that looks like Haskell's <code>do</code> syntax. (The name <code>do</code> is already used as the Scheme and Common Lisp name for a kind of for-loop.)
 
Notice that the <code>&gt;&gt;=</code> and <code>&gt;-&gt;</code> are ordinary "prefix" procedures, rather than infix operators. One might think this would make them very difficult to write with, but a Scheme procedure can be made to recursively perform a chain of operations, so that you will need to write the procedure name only once. I have made <code>&gt;&gt;=</code> and <code>&gt;-&gt;</code> work that way.
 
<pre>
---------------
Using just >>=
---------------
(1 + sqrt(5))/2 = 1.61803398874989
messages:
(new writer-monad 5)
(5 root 2.23606797749979)
(2.23606797749979 addOne 3.23606797749979)
(3.23606797749979 half 1.61803398874989)
 
------------------
Using >>= and >=>
------------------
(1 + sqrt(5))/2 = 1.61803398874989
messages:
(new writer-monad 5)
(5 root 2.23606797749979)
(2.23606797749979 addOne 3.23606797749979)
(3.23606797749979 half 1.61803398874989)
 
-----------------------
Using 'perform' syntax
-----------------------
(1 + sqrt(5))/2 = 1.61803398874989
messages:
(new writer-monad 5)
(5 root 2.23606797749979)
(2.23606797749979 addOne 3.23606797749979)
(3.23606797749979 half 1.61803398874989)
</pre>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt
 
class Mwriter {
construct new(value, log) {
_value = value
_log = log
}
 
value { _value }
log {_log}
log=(value) { _log = value }
 
bind(f) {
var n = f.call(_value)
n.log = _log + n.log
return n
}
 
static unit(v, s) { Mwriter.new(v, " %(Fmt.s(-17, s)): %(v)\n") }
}
 
var root = Fn.new { |v| Mwriter.unit(v.sqrt, "Took square root") }
var addOne = Fn.new { |v| Mwriter.unit(v + 1, "Added one") }
var half = Fn.new { |v| Mwriter.unit( v / 2, "Divided by two") }
 
var mw1 = Mwriter.unit(5, "Initial value")
var mw2 = mw1.bind(root).bind(addOne).bind(half)
System.print("The Golden Ratio is %(mw2.value)")
System.print("\nThis was derived as follows:-")
System.print(mw2.log)</syntaxhighlight>
 
{{out}}
<pre>
The Golden Ratio is 1.6180339887499
 
This was derived as follows:-
Initial value : 5
Took square root : 2.2360679774998
Added one : 3.2360679774998
Divided by two : 1.6180339887499
</pre>
 
=={{header|zkl}}==
{{trans|EchoLisp}}
<langsyntaxhighlight lang="zkl">class Writer{
fcn init(x){ var X=x, logText=Data(Void," init \U2192; ",x.toString()) }
fcn unit(text) { logText.append(text); self }
Line 500 ⟶ 1,596:
fcn half{ lift('/(2),"half") }
fcn inc { lift('+(1),"inc") }
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">Writer(5.0).root().inc().half().println();</langsyntaxhighlight>
{{out}}
<pre>
Line 510 ⟶ 1,606:
half → 1.61803
</pre>
<langsyntaxhighlight lang="zkl">w:=Writer(5.0);
Utils.Helpers.fcomp(w.half,w.inc,w.root)(w).println(); // half(inc(root(w)))</langsyntaxhighlight>
{{out}}
<pre>
Line 521 ⟶ 1,617:
</pre>
Use bind to add functions to an existing Writer:
<langsyntaxhighlight lang="zkl">w:=Writer(5.0);
root,inc,half := w.bind(fcn(x){ x.sqrt() },"root"), w.bind('+(1),"+ 1"), w.bind('/(2),"/ 2");
root(); inc(); half(); w.println();</langsyntaxhighlight>
{{out}}
<pre>
2,122

edits