Monads/Maybe monad: Difference between revisions

m
syntax highlighting fixup automation
(Add OCaml)
m (syntax highlighting fixup automation)
Line 14:
=={{header|ALGOL 68}}==
{{trans|JavaScript}}
<langsyntaxhighlight lang="algol68">BEGIN
 
# This is a translation of the Javascript sample, main differences are because Algol 68 #
Line 139:
print( ( "]", newline ) )
END</langsyntaxhighlight>
{{out}}
<pre>
Line 159:
 
 
<langsyntaxhighlight AppleScriptlang="applescript">property e : 2.71828182846
 
on run {}
Line 297:
return lst
end map
</syntaxhighlight>
</lang>
 
{{Out}}
Line 307:
 
=={{header|C}}==
<syntaxhighlight lang="c">
<lang C>
#include <stdio.h>
#include <stdlib.h>
Line 432:
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>
</lang>
{{out}}
<pre>
Line 443:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <cmath>
#include <optional>
Line 519:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 534:
=={{header|C sharp|C#}}==
 
<langsyntaxhighlight lang="csharp">using System;
 
namespace RosettaMaybe
Line 578:
}
}
}</langsyntaxhighlight>
 
 
=={{header|Clojure}}==
 
<langsyntaxhighlight lang="clojure">
(defn bind [val f]
(if-let [v (:value val)] (f v) val))
Line 596:
(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">
<lang Delphi>
program Maybe_monad;
 
Line 675:
end;
Readln;
end.</langsyntaxhighlight>
{{out}}
<pre> 3 -> 6
Line 686:
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 725:
(->> 1 Maybe.unit (Maybe.bind u-log) (Maybe.bind u-inv) (Maybe.bind number->string) Maybe.print)
→ ❌ (#f . 0)
</syntaxhighlight>
</lang>
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
// We can use Some as return, Option.bind and the pipeline operator in order to have a very concise code
 
Line 737:
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>
</lang>
{{out}}
<pre>
Line 746:
=={{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 755:
! 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 769:
[ 2 * <just> ]
[ 1 + <just> ]
} do .</langsyntaxhighlight>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 821:
fmt.Printf("%4s -> %s\n", s1, s2)
}
}</langsyntaxhighlight>
 
{{out}}
Line 834:
 
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 845:
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 855:
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 870:
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 895:
(some (mul a 2))
--
</syntaxhighlight>
</lang>
 
Hoon has a built-in rune, %smsg (;~) that binds gates under a monad.
Line 918:
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 945:
┌──┐
│_.│
└──┘</langsyntaxhighlight>
 
=={{header|JavaScript}}==
Line 953:
Example: deriving and composing safe versions of reciprocal, square root and log functions.
 
<langsyntaxhighlight JavaScriptlang="javascript">(function () {
'use strict';
 
Line 1,061:
);
 
})();</langsyntaxhighlight>
 
{{Out}}
Line 1,070:
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">struct maybe x::Union{Real, Missing}; end
 
Base.show(io::IO, m::maybe) = print(io, m.x)
Line 1,086:
 
println(b, " -> ", bind(f2, bind(f1, b)))
</langsyntaxhighlight>{{out}}
<pre>
3 -> 19
Line 1,098:
 
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 1,121:
/* prints 'false' as there is no value present in the Optional<String> instance */
println(getOptionalInt(0).flatMap(::getOptionalString2).isPresent)
}</langsyntaxhighlight>
 
{{out}}
Line 1,132:
=={{header|Lua}}==
{{works with|lua|5.3}}
<langsyntaxhighlight 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
Line 1,213:
local outList = map(safeComputation, inList)
print("output:", table.concat(map(maybeToStr, outList), ", "), "\n")
</syntaxhighlight>
</lang>
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">import options,math,sugar,strformat
template checkAndWrap(x:float,body:typed): untyped =
if x.classify in {fcNormal,fcZero,fcNegZero}:
Line 1,239:
when isMainModule:
for i in [0.9,0.0,-0.9,3.0]:
echo some(i) --> reciprocal --> log --> format</langsyntaxhighlight>
{{out}}<pre>some("0.11")
none(string)
Line 1,247:
=={{header|OCaml}}==
The Option module already has our bind and return operations. If we wanted to redefine them :
<langsyntaxhighlight lang="ocaml">let bind opt func = match opt with
| Some x -> func x
| None -> None
 
let return x = Some x</langsyntaxhighlight>
To easily manipulate bind, we can use infix operators and let pruning :
<langsyntaxhighlight lang="ocaml">let (-->) = bind
let (let*) = bind
 
let print_str_opt x =
Format.printf "%s" (Option.value ~default:"None" x)</langsyntaxhighlight>
Example:
<langsyntaxhighlight 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)
Line 1,279:
let* y = if x < 0.0 then None else return (sqrt x) in
return (Format.sprintf "%#f" y)
in print_str_opt v</langsyntaxhighlight>
 
=={{header|Perl}}==
{{trans|Haskell}}
<langsyntaxhighlight Perllang="perl"># 20201101 added Perl programming solution
 
use strict;
Line 1,301:
->flat_map( \&safeLog );
$safeLogRootReciprocal->is_nothing ? "NaN" : $safeLogRootReciprocal->value;
} (-2, -1, -0.5, 0, exp (-1), 1, 2, exp(1), 3, 4, 5) ), "\n";</langsyntaxhighlight>
{{out}}
<pre>NaN NaN NaN NaN 0.5 0 -0.346573590279973 -0.5 -0.549306144334055 -0.693147180559945 -0.80471895621705</pre>
Line 1,309:
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.
<!--<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;">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>
Line 1,331:
<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>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 1,345:
syntax error.
 
<langsyntaxhighlight lang="python">"""A Maybe Monad. Requires Python >= 3.7 for type hints."""
from __future__ import annotations
 
Line 1,397:
# result = m_int.bind(plus_one).bind(currency)
print(f"{str(case):<4} -> {result}")
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,411:
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>.
 
<langsyntaxhighlight lang="racket">#lang racket
 
(require syntax/parse/define)
Line 1,448:
(return x)))
 
(map safe-log-root-reciprocal* tests)</langsyntaxhighlight>
 
{{out}}
Line 1,472:
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 1,492:
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 1,535:
# 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 1,554:
=={{header|REXX}}==
This REXX version is modeled after the Zkl version.
<langsyntaxhighlight lang="rexx">/*REXX program mimics a bind operation when trying to perform addition upon arguments. */
call add 1, 2
call add 1, 2.0
Line 1,577:
end /*k*/
say 'sum=' $
return $</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 1,597:
OOP version using Ruby's block syntax
 
<langsyntaxhighlight lang="ruby">class Maybe
def initialize(value)
@value = value
Line 1,645:
Maybe.unit(nil).bind { |n| Maybe.unit(2*n) }.bind { |n| Maybe.unit(n+1) }
#=> #<Maybe @value=nil>
</syntaxhighlight>
</lang>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-fmt}}
<langsyntaxhighlight lang="ecmascript">import "/fmt" for Fmt
 
class Maybe {
Line 1,680:
var s2 = (m2.value) ? "%(m2.value)" : "none"
System.print("%(Fmt.s(4, s1)) -> %(s2)")
}</langsyntaxhighlight>
 
{{out}}
Line 1,696:
 
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,707:
add(1,2).println(); // two ints
add(1,2.0).println(); // int and float
add(self,2).println(); // class and int</langsyntaxhighlight>
{{out}}
<pre>
10,333

edits