Monads/Maybe monad: Difference between revisions

Added FreeBASIC
(Added FreeBASIC)
 
(48 intermediate revisions by 20 users not shown)
Line 1:
{{draft task}}
[[Category:Monads]]
Demonstrate in your programming language the following:
Line 11:
 
A Maybe Monad is a monad which specifically encapsulates the type of an undefined value.
 
 
=={{header|ALGOL 68}}==
{{trans|JavaScript}}
<langsyntaxhighlight lang="algol68">BEGIN
 
# This is a translation of the Javascript sample, main differences are because Algol 68 #
Line 140 ⟶ 139:
print( ( "]", newline ) )
END</langsyntaxhighlight>
{{out}}
<pre>
Line 160 ⟶ 159:
 
 
<langsyntaxhighlight AppleScriptlang="applescript">property e : 2.71828182846
 
on run {}
Line 298 ⟶ 297:
return lst
end map
</syntaxhighlight>
</lang>
 
{{Out}}
Line 306 ⟶ 305:
 
{missing value, missing value, missing value, missing value, 0.5, 0.0, -0.346573590279, -0.499999999999, -0.549306144333, -0.69314718056, -0.804718956217}</pre>
 
=={{header|ATS}}==
<syntaxhighlight lang="ats">
#include "share/atspre_staload.hats"
 
(* There are "Option" and "Option_vt" in the ATS2 prelude, but I shall
construct something anew. *)
 
datatype Maybe (a : t@ype+) =
| Nothing of ()
| Just of a
 
fn {a, b : t@ype}
bind_Maybe {u : bool}
(m : Maybe a,
f : a -<cloref1> Maybe b) : Maybe b =
case+ m of
| Nothing {a} () => Nothing {b} ()
| Just {a} x => f x
 
infixl 0 >>=
overload >>= with bind_Maybe
 
implement
main0 () =
let
val f : int -<cloref1> Maybe int =
lam i =<cloref1> if (i : int) < 0 then Nothing () else Just i
val g : int -<cloref1> Maybe string =
lam i =<cloref1> Just (tostring_val<int> i)
in
case+ Just 123 >>= f >>= g of
| Nothing () => println! ("Nothing ()")
| Just s => println! ("Just (\"", s : string, "\")");
case+ Just ~123 >>= f >>= g of
| Nothing () => println! ("Nothing ()")
| Just s => println! ("Just (\"", s : string, "\")")
end
</syntaxhighlight>
 
{{out}}
<pre>$ patscc -std=gnu2x -g -O2 -DATS_MEMALLOC_GCBDW maybe_monad_ats.dats -lgc && ./a.out
Just ("123")
Nothing ()</pre>
 
=={{header|C}}==
<syntaxhighlight lang="c">
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
 
typedef enum type
{
INT,
STRING
} Type;
 
typedef struct maybe
{
int i;
char *s;
Type t;
_Bool is_something;
} Maybe;
 
void print_Maybe(Maybe *m)
{
if (m->t == INT)
printf("Just %d : INT\n", m->i);
 
else if (m->t == STRING)
printf("Just \"%s\" : STRING\n", m->s);
 
else
printf("Nothing\n");
 
}
 
Maybe *return_maybe(void *data, Type t)
{
Maybe *m = malloc(sizeof(Maybe));
if (t == INT)
{
m->i = *(int *) data;
m->s = NULL;
m->t = INT;
m->is_something = true;
}
 
else if (t == STRING)
{
m->i = 0;
m->s = data;
m->t = STRING;
m->is_something = true;
}
 
else
{
m->i = 0;
m->s = NULL;
m->t = 0;
m->is_something = false;
}
 
return m;
}
 
Maybe *bind_maybe(Maybe *m, Maybe *(*f)(void *))
{
Maybe *n = malloc(sizeof(Maybe));
if (f(&(m->i))->is_something)
{
n->i = f(&(m->i))->i;
n->s = f(&(m->i))->s;
n->t = f(&(m->i))->t;
n->is_something = true;
}
 
else
{
n->i = 0;
n->s = NULL;
n->t = 0;
n->is_something = false;
}
return n;
}
 
Maybe *f_1(void *v) // Int -> Maybe Int
{
Maybe *m = malloc(sizeof(Maybe));
m->i = (*(int *) v) * (*(int *) v);
m->s = NULL;
m->t = INT;
m->is_something = true;
return m;
}
 
Maybe *f_2(void *v) // :: Int -> Maybe String
{
Maybe *m = malloc(sizeof(Maybe));
m->i = 0;
m->s = malloc(*(int *) v * sizeof(char) + 1);
for (int i = 0; i < *(int *) v; i++)
{
m->s[i] = 'x';
}
m->s[*(int *) v + 1] = '\0';
m->t = STRING;
m->is_something = true;
return m;
}
 
int main()
{
int i = 7;
char *s = "lorem ipsum dolor sit amet";
 
Maybe *m_1 = return_maybe(&i, INT);
Maybe *m_2 = return_maybe(s, STRING);
 
print_Maybe(m_1); // print value of m_1: Just 49
print_Maybe(m_2); // print value of m_2 : Just "lorem ipsum dolor sit amet"
 
print_Maybe(bind_maybe(m_1, f_1)); // m_1 `bind` f_1 :: Maybe Int
print_Maybe(bind_maybe(m_1, f_2)); // m_1 `bind` f_2 :: Maybe String
 
print_Maybe(bind_maybe(bind_maybe(m_1, f_1), f_2)); // (m_1 `bind` f_1) `bind` f_2 :: Maybe String -- it prints 49 'x' characters in a row
}
</syntaxhighlight>
{{out}}
<pre>
Just 7 : INT
Just "lorem ipsum dolor sit amet" : STRING
Just 49 : INT
Just "xxxxxxx" : STRING
Just "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" : STRING
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">#include <iostream>
#include <cmath>
#include <optional>
#include <vector>
 
using namespace std;
 
// std::optional can be a maybe monad. Use the >> operator as the bind function
template <typename T>
auto operator>>(const optional<T>& monad, auto f)
{
if(!monad.has_value())
{
// Return an empty maybe monad of the same type as if there
// was a value
return optional<remove_reference_t<decltype(*f(*monad))>>();
}
 
return f(*monad);
}
 
// The Pure function returns a maybe monad containing the value t
auto Pure(auto t)
{
return optional{t};
}
 
// A safe function to invert a value
auto SafeInverse(double v)
{
if (v == 0)
{
return optional<decltype(v)>();
}
else
{
return optional(1/v);
}
}
 
// A safe function to calculate the arc cosine
auto SafeAcos(double v)
{
if(v < -1 || v > 1)
{
// The input is out of range, return an empty monad
return optional<decltype(acos(v))>();
}
else
{
return optional(acos(v));
}
}
 
// Print the monad
template<typename T>
ostream& operator<<(ostream& s, optional<T> v)
{
s << (v ? to_string(*v) : "nothing");
return s;
}
 
int main()
{
// Use bind to compose SafeInverse and SafeAcos
vector<double> tests {-2.5, -1, -0.5, 0, 0.5, 1, 2.5};
cout << "x -> acos(1/x) , 1/(acos(x)\n";
for(auto v : tests)
{
auto maybeMonad = Pure(v);
auto inverseAcos = maybeMonad >> SafeInverse >> SafeAcos;
auto acosInverse = maybeMonad >> SafeAcos >> SafeInverse;
cout << v << " -> " << inverseAcos << ", " << acosInverse << "\n";
}
}
</syntaxhighlight>
{{out}}
<pre>
x -> acos(1/x) , 1/(acos(x)
-2.5 -> 1.982313, nothing
-1 -> 3.141593, 0.318310
-0.5 -> nothing, 0.477465
0 -> nothing, 0.636620
0.5 -> nothing, 0.954930
1 -> 0.000000, nothing
2.5 -> 1.159279, nothing
</pre>
 
=={{header|C sharp|C#}}==
 
<syntaxhighlight lang="csharp">using System;
 
namespace RosettaMaybe
{
// courtesy of https://www.dotnetcurry.com/patterns-practices/1510/maybe-monad-csharp
public abstract class Maybe<T>
{
public sealed class Some : Maybe<T>
{
public Some(T value) => Value = value;
public T Value { get; }
}
public sealed class None : Maybe<T> { }
}
 
class Program
{
static Maybe<double> MonadicSquareRoot(double x)
{
if (x >= 0)
{
return new Maybe<double>.Some(Math.Sqrt(x));
}
else
{
return new Maybe<double>.None();
}
}
static void Main(string[] args)
{
foreach (double x in new double[] { 4.0D, 8.0D, -15.0D, 16.23D, -42 })
{
Maybe<double> maybe = MonadicSquareRoot(x);
if (maybe is Maybe<double>.Some some)
{
Console.WriteLine($"The square root of {x} is " + some.Value);
}
else
{
Console.WriteLine($"Square root of {x} is undefined.");
}
}
}
}
}</syntaxhighlight>
 
 
=={{header|Clojure}}==
 
<langsyntaxhighlight lang="clojure">
(defn bind [val f]
(if-let [v (:value val)] (f v) val))
Line 322 ⟶ 640:
(bind (bind (unit 8) opt_add_3) opt_str) ; evaluates to {:value "11"}
(bind (bind (unit nil) opt_add_3) opt_str) ; evaluates to {:value nil}
</syntaxhighlight>
</lang>
 
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{Trans|Go}}
<syntaxhighlight lang="delphi">
program Maybe_monad;
 
{$APPTYPE CONSOLE}
 
uses
System.SysUtils;
 
type
TmList = record
Value: PInteger;
function ToString: string;
function Bind(f: TFunc<PInteger, TmList>): TmList;
end;
 
function _Unit(aValue: Integer): TmList; overload;
begin
Result.Value := GetMemory(sizeof(Integer));
Result.Value^ := aValue;
end;
 
function _Unit(aValue: PInteger): TmList; overload;
begin
Result.Value := aValue;
end;
 
{ TmList }
 
function TmList.Bind(f: TFunc<PInteger, TmList>): TmList;
begin
Result := f(self.Value);
end;
 
function TmList.ToString: string;
begin
if Value = nil then
Result := 'none'
else
Result := value^.ToString;
end;
 
function Decrement(p: PInteger): TmList;
begin
if p = nil then
exit(_Unit(nil));
Result := _Unit(p^ - 1);
end;
 
function Triple(p: PInteger): TmList;
begin
if p = nil then
exit(_Unit(nil));
Result := _Unit(p^ * 3);
end;
 
var
m1, m2: TmList;
i, a, b, c: Integer;
p: Tarray<PInteger>;
 
begin
a := 3;
b := 4;
c := 5;
p := [@a, @b, nil, @c];
 
for i := 0 to High(p) do
begin
m1 := _Unit(p[i]);
m2 := m1.Bind(Decrement).Bind(Triple);
 
Writeln(m1.ToString: 4, ' -> ', m2.ToString);
end;
Readln;
end.</syntaxhighlight>
{{out}}
<pre> 3 -> 6
4 -> 9
none -> none
5 -> 12</pre>
 
=={{header|EchoLisp}}==
Line 328 ⟶ 730:
Functions which return something not in Maybe.domain are unsafe and return (#f . input-value), If a function is given as input a (#f . value) element, it will return this element.
 
<langsyntaxhighlight lang="scheme">
(define (Maybe.domain? x) (or (number? x) (string? x)))
(define (Maybe.unit elem (bool #t)) (cons bool elem))
Line 367 ⟶ 769:
(->> 1 Maybe.unit (Maybe.bind u-log) (Maybe.bind u-inv) (Maybe.bind number->string) Maybe.print)
→ ❌ (#f . 0)
</syntaxhighlight>
</lang>
 
=={{header|FreeBASIC}}==
{{trans|Wren}}
<syntaxhighlight lang="vbnet">Type mmaybe
As Integer value
End Type
 
Function Bindf(m As mmaybe, f As Function(As mmaybe) As mmaybe) As mmaybe
Return f(m)
End Function
 
Function Unit(i As Integer) As mmaybe
Dim As mmaybe m
m.value = i
Return m
End Function
 
Function Decrement(mm As mmaybe) As mmaybe
Dim As mmaybe result
result.value = Iif(mm.value = 0, 0, mm.value - 1)
Return Unit(result.value)
End Function
 
Function Triple(mm As mmaybe) As mmaybe
Dim As mmaybe result
result.value = Iif(mm.value = 0, 0, 3 * mm.value)
Return Unit(result.value)
End Function
 
Dim As Integer values(3) = {3, 4, 0, 5}
Dim As Function(As mmaybe) As mmaybe Ptr decrementPtr = @Decrement
Dim As Function(As mmaybe) As mmaybe Ptr triplePtr = @Triple
 
For i As Integer = Lbound(values) To Ubound(values)
Dim As mmaybe m1 = Unit(values(i))
Dim As mmaybe m2 = Bindf(Bindf(m1, decrementPtr), triplePtr)
Dim As String s1 = Iif(m1.value = 0, "none", Str(m1.value))
Dim As String s2 = Iif(m2.value = 0, "none", Str(m2.value))
Print Using "\ \ -> \ \"; s1; s2
Next i
 
Sleep</syntaxhighlight>
{{out}}
<pre> 3 -> 6
4 -> 9
none -> none
5 -> 12</pre>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// We can use Some as return, Option.bind and the pipeline operator in order to have a very concise code
 
 
let f1 (v:int) = Some v // int -> Option<int>
let f2 (v:int) = Some(string v) // int -> Option<sting>
 
f1 4 |> Option.bind f2 |> printfn "Value is %A" // bind when option (maybe) has data
None |> Option.bind f2 |> printfn "Value is %A" // bind when option (maybe) does not have data
</syntaxhighlight>
{{out}}
<pre>
4
null
</pre>
 
=={{header|Factor}}==
Factor comes with an implementation of Haskell-style monads in the <code>monads</code> vocabulary.
<langsyntaxhighlight lang="factor">USING: monads ;
FROM: monads => do ;
 
Line 380 ⟶ 846:
! Prints "nothing"
nothing >>= [ 2 * maybe-monad return ] swap call
>>= [ 1 + maybe-monad return ] swap call .</langsyntaxhighlight>
Or:
<langsyntaxhighlight lang="factor">3 <just> [ 2 * <just> ] bind [ 1 + <just> ] bind .
nothing [ 2 * <just> ] bind [ 1 + <just> ] bind .</langsyntaxhighlight>
Or with <code>do</code> notation:
<langsyntaxhighlight lang="factor">{
[ 3 <just> ]
[ 2 * <just> ]
Line 394 ⟶ 860:
[ 2 * <just> ]
[ 1 + <just> ]
} do .</langsyntaxhighlight>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 446 ⟶ 912:
fmt.Printf("%4s -> %s\n", s1, s2)
}
}</langsyntaxhighlight>
 
{{out}}
Line 459 ⟶ 925:
 
Haskell has the built-in <code>Monad</code> type class, and the built-in <code>Maybe</code> type already conforms to the <code>Monad</code> type class.
<langsyntaxhighlight lang="haskell">main = do print $ Just 3 >>= (return . (*2)) >>= (return . (+1)) -- prints "Just 7"
print $ Nothing >>= (return . (*2)) >>= (return . (+1)) -- prints "Nothing"</langsyntaxhighlight>
 
Or, written using <code>do</code> notation:
<langsyntaxhighlight lang="haskell">main = do print (do x <- Just 3
y <- return (x*2)
z <- return (y+1)
Line 470 ⟶ 936:
y <- return (x*2)
z <- return (y+1)
return z)</langsyntaxhighlight>
 
Or alternately:
<langsyntaxhighlight lang="haskell">main = do print (do x <- Just 3
let y = x*2
let z = y+1
Line 480 ⟶ 946:
let y = x*2
let z = y+1
return z)</langsyntaxhighlight>
 
Deriving and composing safe versions of reciprocal, square root and log functions. :
<langsyntaxhighlight lang="haskell">import Control.Monad ((>=>))
 
safeVersion :: (a -> b) -> (a -> Bool) -> a -> Maybe b
Line 495 ⟶ 961:
safeLogRootReciprocal = safeReciprocal >=> safeRoot >=> safeLog
 
main = print $ map safeLogRootReciprocal [-2, -1, -0.5, 0, exp (-1), 1, 2, exp 1, 3, 4, 5]</langsyntaxhighlight>
{{out}}
<pre>[Nothing,Nothing,Nothing,Nothing,Just 0.5,Just 0.0,Just (-0.3465735902799726),Just (-0.5),Just (-0.5493061443340549),Just (-0.6931471805599453),Just (-0.8047189562170503)]</pre>
 
=={{header|Hoon}}==
<langsyntaxhighlight lang="hoon">
:- %say
|= [^ [[txt=(unit ,@tas) ~] ~]]
Line 520 ⟶ 986:
(some (mul a 2))
--
</syntaxhighlight>
</lang>
 
Hoon has a built-in rune, %smsg (;~) that binds gates under a monad.
Line 543 ⟶ 1,009:
It's difficult to find a useful and illustrative (but simple) example of this task in J. So we shall not try to be useful.
 
<syntaxhighlight lang="j">
<lang J>
NB. monad implementation:
unit=: <
Line 570 ⟶ 1,036:
┌──┐
│_.│
└──┘</langsyntaxhighlight>
 
=={{header|Java}}==
Java has a built-in generic "Maybe" monad in form of the Optional<T> class.
 
The class has static methods, "of" and "ofNullable", which act as the unit function
for wrapping nullable and non-nullable values respectively.
 
The class instance method, "flatMap", acts as the bind function.
<syntaxhighlight lang="java">
import java.util.Optional;
 
public final class MonadMaybe {
 
public static void main(String[] aArgs) {
System.out.println(doubler(5).flatMap(MonadMaybe::stringify).get());
System.out.println(doubler(2).flatMap(MonadMaybe::stringifyNullable).get());
Optional<String> option = doubler(0).flatMap(MonadMaybe::stringifyNullable);
String result = option.isPresent() ? option.get() : "Result is Null";
System.out.println(result);
}
private static Optional<Integer> doubler(int aN) {
return Optional.of(2 * aN);
}
 
private static Optional<String> stringify(int aN) {
return Optional.of("A".repeat(aN));
}
 
private static Optional<String> stringifyNullable(int aN) {
return ( aN > 0 ) ? Optional.ofNullable("A".repeat(aN)) : Optional.ofNullable(null);
}
 
}
</syntaxhighlight>
{{ out }}
<pre>
AAAAAAAAAA
AAAA
Result is Null
</pre>
 
=={{header|JavaScript}}==
Line 578 ⟶ 1,089:
Example: deriving and composing safe versions of reciprocal, square root and log functions.
 
<langsyntaxhighlight JavaScriptlang="javascript">(function () {
'use strict';
 
Line 686 ⟶ 1,197:
);
 
})();</langsyntaxhighlight>
 
{{Out}}
Line 695 ⟶ 1,206:
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">struct maybe x::Union{Real, Missing}; end
 
Base.show(io::IO, m::maybe) = print(io, m.x)
Line 711 ⟶ 1,222:
 
println(b, " -> ", bind(f2, bind(f1, b)))
</langsyntaxhighlight>{{out}}
<pre>
3 -> 19
Line 723 ⟶ 1,234:
 
Rather than write something from scratch, we use this class to complete this task.
<langsyntaxhighlight lang="scala">// version 1.2.10
 
import java.util.Optional
Line 746 ⟶ 1,257:
/* prints 'false' as there is no value present in the Optional<String> instance */
println(getOptionalInt(0).flatMap(::getOptionalString2).isPresent)
}</langsyntaxhighlight>
 
{{out}}
Line 755 ⟶ 1,266:
</pre>
 
=={{header|Perl 6Lua}}==
{{works with|lua|5.3}}
<syntaxhighlight lang="lua">
-- None is represented by an empty table. Some is represented by any
-- array with one element. You SHOULD NOT compare maybe values with the
-- Lua operator == because it will give incorrect results. Use the
-- functions isMaybe(), isNone(), and isSome().
 
-- define once for efficiency, to avoid many different empty tables
local NONE = {}
 
local function unit(x) return { x } end
local Some = unit
local function isNone(mb) return #mb == 0 end
local function isSome(mb) return #mb == 1 end
local function isMaybe(mb) return isNone(mb) or isSome(mb) end
 
-- inverse of Some(), extract the value from the maybe; get(Some(x)) === x
local function get(mb) return mb[1] end
 
function maybeToStr(mb)
return isNone(mb) and "None" or ("Some " .. tostring(get(mb)))
end
 
local function bind(mb, ...) -- monadic bind for multiple functions
local acc = mb
for _, fun in ipairs({...}) do -- fun should be a monadic function
assert(type(fun) == "function")
if isNone(acc) then return NONE
else acc = fun(get(acc)) end
end
return acc
end
 
local function fmap(mb, ...) -- monadic fmap for multiple functions
local acc = mb
for _, fun in ipairs({...}) do -- fun should be a regular function
assert(type(fun) == "function")
if isNone(acc) then return NONE
else acc = Some(fun(get(acc))) end
end
return acc
end
-- ^^^ End of generic maybe monad functionality ^^^
 
--- vvv Start of example code vvv
 
local function time2(x) return x * 2 end
local function plus1(x) return x + 1 end
 
local answer
answer = fmap(Some(3), time2, plus1, time2)
assert(get(answer)==14)
 
answer = fmap(NONE, time2, plus1, time2)
assert(isNone(answer))
 
local function safeReciprocal(x)
if x ~= 0 then return Some(1/x) else return NONE end
end
local function safeRoot(x)
if x >= 0 then return Some(math.sqrt(x)) else return NONE end
end
local function safeLog(x)
if x > 0 then return Some(math.log(x)) else return NONE end
end
local function safeComputation(x)
return bind(safeReciprocal(x), safeRoot, safeLog)
end
 
local function map(func, table)
local result = {}
for key, val in pairs(table) do
result[key] = func(val)
end
return result
end
 
local inList = {-2, -1, -0.5, 0, math.exp (-1), 1, 2, math.exp (1), 3, 4, 5}
print("input:", table.concat(map(tostring, inList), ", "), "\n")
 
local outList = map(safeComputation, inList)
print("output:", table.concat(map(maybeToStr, outList), ", "), "\n")
</syntaxhighlight>
 
 
=={{header|M2000 Interpreter}}==
Revision 1. Now the operator "=" check if we have same status on haveValue for the two objects. If not we get the false in compare. Also the unit() function return "none" object from a an object not "none".
 
M2000 create objects (of type Group) either from a Class (which is a function), or from a copy of an object. The life of an object depends of the storing site, and the use of a pointer or not. Here all objects are one of two kinds: Objects like none, m1, m2, m3 and m5 are destruct at the exit of the module. Object on the SetA like none and none.unit() (which is a copy of none), destruct when last pointer (here SetA) deleted, and for this example, because SetA is local variable, the delete happen at the exit of current module. The m object which used in Bind() and Unit() function, and the g object are all objects which life end at the exit of those function, although these functions return a pointer to a copy of the m object, and check an internal field which make it "float". A float object is something different from an object holding by a pointer. M2000 always "expand" a float object when we place it to a variable (as a copy, or if the variable hold another object - always as group else we get error 0 - as a merge of these). So when we pick a "float" object from array, we get a copy. M2000 can use pointer to groups. The second list show how we can use pointers to groups. Pointers can be one of two types: A real pointes (here we use real pointers), or a weak pointer. The -> operator in a ->m (or =pointer(m)) where m hold a group (not a pointer) return a weak pointer (invalid if actual variable not exist). Here we use ->(m) which make m a float group and then change it to a pointer to float group (same as =pointer((m))). A pointer(none) return a real pointer if none is a pointer to group, or a weak pointer if it isn't a pointer. A pointer to group is a group, not an address. A pointer() return the Null pointer (which is a group of type Null). The Null group (user object in M2000), has a type that cannot inherit to other classes, also in a group merge with null we don't merge Null type. Merging is another way to produce groups from two or more other types, using objects (not classes).
 
===== Without using pointers =====
 
<syntaxhighlight lang="m2000 interpreter">
Class maybe {
private:
variant [val]="none"
boolean haveValue
public:
property val {
value // val return the [val] value
}
function bind(f) {
m=This // we can read private because bind is function of same class as m
if m.haveValue Then m.[val]=f(m.[val])
=m // copy (not pointer)
}
Operator "=" (z as maybe) {
if z.havevalue xor .havevalue then
push false
else
Push z.[val]=.[val]
end if
}
Function unit() {
variant k
if match("G") then // so we can read maybe class
read g as maybe // fail if not maybe class
if g.havevalue then push g.val
end if
Read ? k
m=This
if not type$(k)="Empty" then
integer v=k ' fail if k can't convert to integer
m.[val]=v
m.haveValue=true
else // so now we can produce "none" from an object which isn't "none"
m.[val]="none"
m.haveValue=false
end if
=m // copy (not pointer)
}
class:
// after class: all are temporary for the constuction phase
// module with class name is the contructor
// the object constracted before enter this module
// but we can change it. So we return a new one.
module maybe {
// so the constructor is the same as the .unit
// ![] pick argument list and place to unit()
// optionally we can skip the call if we have empty argument list
if not empty then
this=.unit(![])
end if
}
}
none=maybe()
decrement =lambda (x as integer)->x-1%
triple =lambda (x as integer)->x*3%
variant emptyvariant
// 3 and 4 are double, 5 is integer type
SetA=(3,4,none,5%, emptyvariant, none.unit())
k=each(SetA)
While K
m1=none.unit(array(k)) // pick element k^
m2=m1.bind(decrement).bind(triple)
m3=maybe(m2)
Print m1.val+" -> "+m2.val, m3=m2, m3.val
End While
Try ok {
m5=maybe("Hello")
}
Print not ok // true , "Hello" not accepted
</syntaxhighlight>
 
 
===== Using pointers =====
 
 
<syntaxhighlight lang="m2000 interpreter">
Class maybe {
private:
variant [val]="none"
boolean haveValue
public:
property val {
value // val return the [val] value
}
function bind(f) {
m=This // we can read private because bind is function of same class as m
if m.haveValue Then m.[val]=f(m.[val])
->(m) // pointer
}
Operator "=" (z as maybe) {
if z.havevalue xor .havevalue then
push false
else
Push z.[val]=.[val]
end if
}
Function unit() {
variant k
if match("G") then // so we can read maybe class
read g as maybe // fail if not maybe class
if g.havevalue then push g.val
end if
Read ? k
m=This
if not type$(k)="Empty" then
integer v=k ' fail if k can't convert to integer
m.[val]=v
m.haveValue=true
else // so now we can produce "none" from an object which isn't "none"
m.[val]="none"
m.haveValue=false
end if
->(m) // pointer
}
class:
module maybe {
if not empty then
this=.unit(![])
end if
}
}
none->maybe()
decrement =lambda (x as integer)->x-1%
triple =lambda (x as integer)->x*3%
variant emptyvariant
SetA=(3,4,none,5%, emptyvariant, none=>unit())
k=each(SetA)
document doc$
While k
m1=none=>unit(array(k)) // pick element k^
m2=m1=>bind(decrement)=>bind(triple)
m3=maybe(m2)
doc$=m1=>val+" -> "+m2=>val+" m2=m3 -> "+if$(m2=m3->"True", "False")+{
}
End While
Try ok {
m5=maybe("Hello")
}
Doc$= (not ok)+{
} // true , "Hello" not accepted
report doc$
clipboard doc$
</syntaxhighlight>
{{out}}
<pre>
3 -> 6 True 6
4 -> 9 True 9
none -> none True none
5 -> 12 True 12
none -> none True none
none -> none True none
True
</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">import options,math,sugar,strformat
template checkAndWrap(x:float,body:typed): untyped =
if x.classify in {fcNormal,fcZero,fcNegZero}:
some(body)
else:
none(typeof(body))
func reciprocal(x:float):Option[float] =
let res = 1 / x
res.checkAndWrap(res)
func log(x:float):Option[float] =
let res = ln(x)
res.checkAndWrap(res)
func format(x:float):Option[string] =
x.checkAndWrap(&"{x:.2f}")
 
#our bind function:
func `-->`[T,U](input:Option[T], f: T->Option[U]):Option[U] =
if input.isSome:
f(input.get)
else:
none(U)
 
when isMainModule:
for i in [0.9,0.0,-0.9,3.0]:
echo some(i) --> reciprocal --> log --> format</syntaxhighlight>
{{out}}<pre>some("0.11")
none(string)
none(string)
some("-1.10")</pre>
 
=={{header|OCaml}}==
The Option module already has our bind and return operations. If we wanted to redefine them :
<syntaxhighlight lang="ocaml">let bind opt func = match opt with
| Some x -> func x
| None -> None
 
let return x = Some x</syntaxhighlight>
To easily manipulate bind, we can use infix operators and let pruning :
<syntaxhighlight lang="ocaml">let (-->) = bind
let (let*) = bind
 
let print_str_opt x =
Format.printf "%s" (Option.value ~default:"None" x)</syntaxhighlight>
Example:
<syntaxhighlight lang="ocaml">let safe_div x y = if y = 0.0 then None else return (x /. y)
let safe_root x = if x < 0.0 then None else return (sqrt x)
let safe_str x = return (Format.sprintf "%#f" x)
 
(* Version 1 : explicit calls *)
let () =
let v = bind (bind (safe_div 5. 3.) safe_root) safe_str in
print_str_opt v
 
(* Version 2 : with an operator *)
let () =
let v = safe_div 5. 3. --> safe_root --> safe_str in
print_str_opt v
 
(* Version 3 : let pruning really shine when inlining functions *)
let () =
let v =
let* x = safe_div 5. 3. in
let* y = if x < 0.0 then None else return (sqrt x) in
return (Format.sprintf "%#f" y)
in print_str_opt v</syntaxhighlight>
 
=={{header|Perl}}==
{{trans|Haskell}}
<syntaxhighlight lang="perl"># 20201101 added Perl programming solution
 
use strict;
use warnings;
 
use Data::Monad::Maybe;
 
sub safeReciprocal { ( $_[0] == 0 ) ? nothing : just( 1 / $_[0] ) }
 
sub safeRoot { ( $_[0] < 0 ) ? nothing : just( sqrt( $_[0] ) ) }
 
sub safeLog { ( $_[0] <= 0 ) ? nothing : just( log ( $_[0] ) ) }
 
print join(' ', map {
my $safeLogRootReciprocal = just($_)->flat_map( \&safeReciprocal )
->flat_map( \&safeRoot )
->flat_map( \&safeLog );
$safeLogRootReciprocal->is_nothing ? "NaN" : $safeLogRootReciprocal->value;
} (-2, -1, -0.5, 0, exp (-1), 1, 2, exp(1), 3, 4, 5) ), "\n";</syntaxhighlight>
{{out}}
<pre>NaN NaN NaN NaN 0.5 0 -0.346573590279973 -0.5 -0.549306144334055 -0.693147180559945 -0.80471895621705</pre>
 
=={{header|Phix}}==
{{trans|Julia}}
Phix has an "object" type which can be an integer or a string, so not entirely un-like Perl.<br>
Here we simply treat all strings or rather non-integers as the "unknown" type.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">function</span> <span style="color: #000000;">bindf</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;">times_five</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">l</span><span style="color: #0000FF;">*</span><span style="color: #000000;">5</span><span style="color: #0000FF;">:</span><span style="color: #000000;">l</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;">plus_four</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">l</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span><span style="color: #0000FF;">:</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">l</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;">l</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;">l</span><span style="color: #0000FF;">,</span><span style="color: #000000;">times_five</span><span style="color: #0000FF;">),</span><span style="color: #000000;">plus_four</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"none"</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
3 -> 19
"none" -> "none"
</pre>
 
=={{header|Python}}==
 
The <code>Maybe</code> class constructor is effectively the <code>unit</code> function. Note that I've used <code>>></code> as the bind operator. Trying to chain <code>__irshift__</code> (<code>>>=</code>) would be a syntax error.
 
<syntaxhighlight lang="python">
"""A Maybe monad. Requires Python >= 3.7 for type hints."""
from __future__ import annotations
 
from typing import Callable
from typing import Generic
from typing import Optional
from typing import TypeVar
from typing import Union
 
 
T = TypeVar("T")
U = TypeVar("U")
 
 
class Maybe(Generic[T]):
def __init__(self, value: Union[Optional[T], Maybe[T]] = None):
if isinstance(value, Maybe):
self.value: Optional[T] = value.value
else:
self.value = value
 
def __rshift__(self, func: Callable[[Optional[T]], Maybe[U]]) -> Maybe[U]:
return self.bind(func)
 
def bind(self, func: Callable[[Optional[T]], Maybe[U]]) -> Maybe[U]:
return func(self.value)
 
def __str__(self):
return f"{self.__class__.__name__}({self.value!r})"
 
 
def plus_one(value: Optional[int]) -> Maybe[int]:
if value is not None:
return Maybe(value + 1)
return Maybe(None)
 
 
def currency(value: Optional[int]) -> Maybe[str]:
if value is not None:
return Maybe(f"${value}.00")
return Maybe(None)
 
 
if __name__ == "__main__":
test_cases = [1, 99, None, 4]
 
for case in test_cases:
result = Maybe(case) >> plus_one >> currency
 
# or..
# result = Maybe(case).bind(plus_one).bind(currency)
 
print(f"{str(case):<4} -> {result}")
</syntaxhighlight>
 
{{out}}
<pre>
1 -> Maybe('$2.00')
99 -> Maybe('$100.00')
None -> Maybe(None)
4 -> Maybe('$5.00')
</pre>
 
=={{header|Racket}}==
 
It is idiomatic in Racket to use <code>#f</code> for <code>Nothing</code>, and every other value is considered implicitly tagged with <code>Just</code>.
 
<syntaxhighlight lang="racket">#lang racket
 
(require syntax/parse/define)
 
(define (bind x f) (and x (f x)))
(define return identity)
 
;; error when arg = 0
(define reciprocal (curry / 1))
;; error when arg < 0
(define (root x) (if (< x 0) (error 'bad) (sqrt x)))
;; error whe arg <= 0
(define (ln x) (if (<= x 0) (error 'bad) (log x)))
 
(define (lift f check) (λ (x) (and (check x) (f x))))
 
(define safe-reciprocal (lift reciprocal (negate (curry equal? 0))))
(define safe-root (lift root (curry <= 0)))
(define safe-ln (lift ln (curry < 0)))
 
(define (safe-log-root-reciprocal x)
(bind (bind (bind x safe-reciprocal) safe-root) safe-ln))
 
(define tests `(-2 -1 -0.5 0 1 ,(exp -1) 1 2 ,(exp 1) 3 4 5))
 
(map safe-log-root-reciprocal tests)
 
(define-syntax-parser do-macro
[(_ [x {~datum <-} y] . the-rest) #'(bind y (λ (x) (do-macro . the-rest)))]
[(_ e) #'e])
 
(define (safe-log-root-reciprocal* x)
(do-macro [x <- (safe-reciprocal x)]
[x <- (safe-root x)]
[x <- (safe-ln x)]
(return x)))
 
(map safe-log-root-reciprocal* tests)</syntaxhighlight>
 
{{out}}
<pre>
'(#f #f #f #f 0 0.5 0 -0.3465735902799726 -0.5 -0.5493061443340549 -0.6931471805599453 -0.8047189562170503)
'(#f #f #f #f 0 0.5 0 -0.3465735902799726 -0.5 -0.5493061443340549 -0.6931471805599453 -0.8047189562170503)
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2019.11}}
It is exceptionally difficult to come up with a compelling valuable use for
a Maybe monad in Perl 6Raku. Monads are most useful in languages that don't have
exceptions and/or only allow a single point of entry/exit from a subroutine.
 
Line 767 ⟶ 1,768:
 
The task description asks for two functions that take an Int and return a Maybe
Int or Maybe Str, but those distinctions are nearly meaningless in Perl 6Raku. See
below.
 
<syntaxhighlight lang="raku" perl6line>my $monad = <42>;
say 'Is $monad an Int?: ', $monad ~~ Int;
say 'Is $monad a Str?: ', $monad ~~ Str;
say 'Wait, what? What exactly is $monad?: ', $monad.^name;</langsyntaxhighlight>
{{out}}
<pre>Is $monad an Int?: True
Line 781 ⟶ 1,782:
$monad is both an Int '''and''' a Str. It exists in a sort-of quantum state
where what-it-is depends on how-it-is-used. Bolting on some 'Monad' type to do
this will only ''remove'' functionality that Perl 6Raku already has.
 
Ok, say you have a situation where you absolutely do not want an incalculable
Line 790 ⟶ 1,791:
candidate.
 
<syntaxhighlight lang="raku" perl6line># Build a Nothing type. When treated as a string it returns the string 'Nothing'.
# When treated as a Numeric, returns the value 'Nil'.
class NOTHING {
Line 833 ⟶ 1,834:
# all; but Ethiopic number 30, times vulgar fraction 1/7, is.
put ($_, .&recip, .&root, .&ln, .&(&ln o &root o &recip) )».&center
for -2, -1, -0.5, 0, exp(-1), 1, 2, exp(1), 3, 4, 5, 'WAT', ፴ × ⅐;</langsyntaxhighlight>
{{out}}
<pre> "Number" Reciprocal Square root Natural log Composed
Line 850 ⟶ 1,851:
4.285714 0.233333 2.0701966780270626 1.455287232606842 -0.727643616303421</pre>
 
=={{header|PhixREXX}}==
This REXX version is modeled after the Zkl version.
{{trans|Julia}}
<syntaxhighlight lang="rexx">/*REXX program mimics a bind operation when trying to perform addition upon arguments. */
Phix has an "object" type which can be an integer or a string, so not entirely un-like Perl.<br>
call add 1, 2
Here we simply treat all strings or rather non-integers as the "unknown" type.
call add 1, 2.0
<lang Phix>function bind(object m, integer f)
call add 1, 2.0, -6
return f(m)
call add self, 2
end function
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
function unit(object m)
add: void= 'VOID'; f= /*define in terms of a function&binding*/
return m
do j=1 for arg() /*process, classify, bind each argument*/
end function
call bind( arg(j) ); f= f arg(j)
end /*j*/
function times_five(object l)
say
return iff(integer(l)?l*5:l)
say 'adding' f; call sum f /*telegraph what's being performed next*/
end function
return /*Note: REXX treats INT & FLOAT as num.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
function plus_four(object l)
bind: arg a; type.a= datatype(a); return /*bind argument's kind with its "type".*/
return iff(integer(l)?l+4:l)
/*──────────────────────────────────────────────────────────────────────────────────────*/
end function
sum: parse arg a; $= 0 /*sum all arguments that were specified*/
 
do k=1 for words(a); ?= word(a, k)
procedure test(object l)
if type.?==num & $\==void then $= ($ + word(a, k)) / 1
printf(1,"%v -> %v\n", {l, bind(bind(l,times_five),plus_four)})
else $= void
end procedure
end /*k*/
test(3)
say 'sum=' $
test("none")</lang>
return $</syntaxhighlight>
{{out}}
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
adding 1 2
3 -> 19
sum= 3
"none" -> "none"
</pre>
 
adding 1 2.0
=={{header|Racket}}==
sum= 3
 
adding 1 2.0 -6
It is idiomatic in Racket to use <code>#f</code> for <code>Nothing</code>, and every other value is considered implicitly tagged with <code>Just</code>.
sum= -3
 
adding SELF 2
<lang racket>#lang racket
sum= VOID
 
(require syntax/parse/define)
 
(define (bind x f) (and x (f x)))
(define return identity)
 
;; error when arg = 0
(define reciprocal (curry / 1))
;; error when arg < 0
(define (root x) (if (< x 0) (error 'bad) (sqrt x)))
;; error whe arg <= 0
(define (ln x) (if (<= x 0) (error 'bad) (log x)))
 
(define (lift f check) (λ (x) (and (check x) (f x))))
 
(define safe-reciprocal (lift reciprocal (negate (curry equal? 0))))
(define safe-root (lift root (curry <= 0)))
(define safe-ln (lift ln (curry < 0)))
 
(define (safe-log-root-reciprocal x)
(bind (bind (bind x safe-reciprocal) safe-root) safe-ln))
 
(define tests `(-2 -1 -0.5 0 1 ,(exp -1) 1 2 ,(exp 1) 3 4 5))
 
(map safe-log-root-reciprocal tests)
 
(define-syntax-parser do-macro
[(_ [x {~datum <-} y] . the-rest) #'(bind y (λ (x) (do-macro . the-rest)))]
[(_ e) #'e])
 
(define (safe-log-root-reciprocal* x)
(do-macro [x <- (safe-reciprocal x)]
[x <- (safe-root x)]
[x <- (safe-ln x)]
(return x)))
 
(map safe-log-root-reciprocal* tests)</lang>
 
{{out}}
<pre>
'(#f #f #f #f 0 0.5 0 -0.3465735902799726 -0.5 -0.5493061443340549 -0.6931471805599453 -0.8047189562170503)
'(#f #f #f #f 0 0.5 0 -0.3465735902799726 -0.5 -0.5493061443340549 -0.6931471805599453 -0.8047189562170503)
</pre>
 
Line 934 ⟶ 1,896:
OOP version using Ruby's block syntax
 
<langsyntaxhighlight lang="ruby">class Maybe
def initialize(value)
@value = value
Line 982 ⟶ 1,944:
Maybe.unit(nil).bind { |n| Maybe.unit(2*n) }.bind { |n| Maybe.unit(n+1) }
#=> #<Maybe @value=nil>
</syntaxhighlight>
</lang>
 
=={{header|Rust}}==
The <code>Maybe</code> monad is called <code>Option<T></code> in Rust, it's widely used in the standard library and user code for functions that might not have sensible return values in certain cases but it's not an error/failure, such as a key doesn't exist for a hash map.
 
In addition, pure/just/return is <code>Some(T)</code> and bind is <code>Option::<T>::and_then(self, F)</code>.
 
<syntaxhighlight lang="Rust">
use std::collections::HashMap;
 
/// Returns the arithmetic square root of x, if it exists
fn arithmetic_square_root(x: u8) -> Option<u8> {
// the number of perfect squares for u8 is so low you can just fit the entire list in memory
let perfect_squares: HashMap<u8, u8> = HashMap::from([
(0, 0),
(1, 1),
(4, 2),
(9, 3),
(16, 4),
(25, 5),
(36, 6),
(49, 7),
(64, 8),
(81, 9),
(100, 10),
(121, 11),
(144, 12),
(169, 13),
(196, 14),
(225, 15),
]);
 
// `HashMap::<K, V>::get(&self, &Q)` also returns a `Option<&V>`, we then turn it to `Option<V>`
perfect_squares.get(&x).copied()
}
 
 
/// If x in base 10 is also a valid number when looking upside down, return a string slice for that
/// number upside down
fn upside_down_num(x: u8) -> Option<&'static str> {
match x {
0 => Some("0"),
1 => Some("1"),
6 => Some("9"),
8 => Some("8"),
9 => Some("6"),
10 => Some("01"),
11 => Some("11"),
16 => Some("91"),
_ => None
}
}
 
fn main() {
// if the number from 0 to 36 inclusive, is a perfect square and its square root is also a
// valid number when looking upside down, then we will get a Some containing the string slice,
// otherwise we get a None, indicating it's not a perfect square or the square root is not a
// valid number while looking upside down
(0..=36)
.map(|x| arithmetic_square_root(x).and_then(upside_down_num))
.enumerate()
.for_each(|(i, upside_down_square_root)|
println!("i = {i:02}, upside down square root = {upside_down_square_root:?}"));
}
</syntaxhighlight>
 
{{out}}
<pre>
i = 00, upside down square root = Some("0")
i = 01, upside down square root = Some("1")
i = 02, upside down square root = None
i = 03, upside down square root = None
i = 04, upside down square root = None
i = 05, upside down square root = None
i = 06, upside down square root = None
i = 07, upside down square root = None
i = 08, upside down square root = None
i = 09, upside down square root = None
i = 10, upside down square root = None
i = 11, upside down square root = None
i = 12, upside down square root = None
i = 13, upside down square root = None
i = 14, upside down square root = None
i = 15, upside down square root = None
i = 16, upside down square root = None
i = 17, upside down square root = None
i = 18, upside down square root = None
i = 19, upside down square root = None
i = 20, upside down square root = None
i = 21, upside down square root = None
i = 22, upside down square root = None
i = 23, upside down square root = None
i = 24, upside down square root = None
i = 25, upside down square root = None
i = 26, upside down square root = None
i = 27, upside down square root = None
i = 28, upside down square root = None
i = 29, upside down square root = None
i = 30, upside down square root = None
i = 31, upside down square root = None
i = 32, upside down square root = None
i = 33, upside down square root = None
i = 34, upside down square root = None
i = 35, upside down square root = None
i = 36, upside down square root = Some("9")
</pre>
 
=={{header|Swift}}==
{{works with|Swift|5}}
Swift has a "Maybe" type built in, called "Optional". I created a typealias so I could adhere to the naming convention. The unit function is also strictly unnecessary because Optional's constructor serves the same purpose. bind is also strictly unnecessary because Swift's Optional.flatmap function does the same thing.
 
I also created an infix operator analogous to Haskell's >>=. I can't use >>= itself because it already exists (left shift assignment) and I can't control the precedence.
 
<syntaxhighlight lang="Swift">
precedencegroup MonadPrecedence {
higherThan: BitwiseShiftPrecedence
associativity: left
}
 
infix operator >>-: MonadPrecedence // Monadic bind
 
typealias Maybe = Optional
 
extension Maybe
{
static func unit(_ x: Wrapped) -> Maybe<Wrapped>
{
return Maybe(x)
}
 
func bind<T>(_ f: (Wrapped) -> Maybe<T>) -> Maybe<T>
{
return self.flatMap(f)
}
 
static func >>- <U>(_ m: Optional<Wrapped>, _ f: (Wrapped) -> Maybe<U>) -> Maybe<U>
{
return m.flatMap(f)
}
}
 
func dividedBy2IfEven(_ x: Int) -> Maybe<Int>
{
x.isMultiple(of: 2) ? x / 2 : nil
}
 
func lineOfAs(_ x: Int) -> Maybe<String>
{
guard x >= 0 else { return nil }
let chars = Array<Character>(repeating: "A", count: x)
return String(chars)
}
 
print("\(Maybe.unit(6).bind(dividedBy2IfEven).bind(lineOfAs) ?? "nil")")
print("\(Maybe.unit(4) >>- dividedBy2IfEven >>- lineOfAs ?? "nil")")
print("\(Maybe.unit(3) >>- dividedBy2IfEven >>- lineOfAs ?? "nil")")
print("\(Maybe.unit(-4) >>- dividedBy2IfEven >>- lineOfAs ?? "nil")")
</syntaxhighlight>
 
{{out}}
<pre>
AAA
AA
nil
nil
</pre>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt
 
class Maybe {
construct new(value) {
_value = value
}
 
value { _value }
 
bind(f) { f.call(_value) }
 
static unit(i) { Maybe.new(i) }
}
 
var decrement = Fn.new { |i|
if (!i) return Maybe.unit(null)
return Maybe.unit(i - 1)
}
 
var triple = Fn.new { |i|
if (!i) return Maybe.unit(null)
return Maybe.unit(3 * i)
}
 
for (i in [3, 4, null, 5]) {
var m1 = Maybe.unit(i)
var m2 = m1.bind(decrement).bind(triple)
var s1 = (m1.value) ? "%(m1.value)" : "none"
var s2 = (m2.value) ? "%(m2.value)" : "none"
Fmt.print("$4s -> $s", s1, s2)
}</syntaxhighlight>
 
{{out}}
<pre>
3 -> 6
4 -> 9
none -> none
5 -> 12
</pre>
 
=={{header|zkl}}==
Line 990 ⟶ 2,160:
 
Here we use the Void object as Nothing and define some functions. Since zkl is type-less, we can consider Maybe as a native type and don't need to define it.
<langsyntaxhighlight lang="zkl">fcn bind(a,type,b){ if(type.isType(a)) b else Void }
fcn just(x){ if(Deferred.isType(x)) x() else x } // force lazy evaluation
fcn rtn(x) { just(x) }</langsyntaxhighlight>
Since zkl is eager, add needs to gyrate a bit by creating a lazy result and evaluating that after the binds have done their bizness.
<langsyntaxhighlight lang="zkl">fcn add(mx,my){
bind(mx,Int,
bind(my,Int,
Line 1,001 ⟶ 2,171:
add(1,2).println(); // two ints
add(1,2.0).println(); // int and float
add(self,2).println(); // class and int</langsyntaxhighlight>
{{out}}
<pre>
2,122

edits