Monads/Maybe monad: Difference between revisions
Content added Content deleted
(Realize in F#) |
Thundergnat (talk | contribs) (Rename Perl 6 -> Raku, alphabetize, minor clean-up) |
||
Line 11: | Line 11: | ||
A Maybe Monad is a monad which specifically encapsulates the type of an undefined value. |
A Maybe Monad is a monad which specifically encapsulates the type of an undefined value. |
||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
Line 398: | Line 397: | ||
Index out of range |
Index out of range |
||
</pre> |
</pre> |
||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
Factor comes with an implementation of Haskell-style monads in the <code>monads</code> vocabulary. |
Factor comes with an implementation of Haskell-style monads in the <code>monads</code> vocabulary. |
||
Line 869: | Line 869: | ||
</lang> |
</lang> |
||
=={{header| |
=={{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. |
|||
<lang Phix>function bind(object m, integer f) |
|||
return f(m) |
|||
end function |
|||
function unit(object m) |
|||
return m |
|||
end function |
|||
function times_five(object l) |
|||
return iff(integer(l)?l*5:l) |
|||
end function |
|||
function plus_four(object l) |
|||
return iff(integer(l)?l+4:l) |
|||
end function |
|||
procedure test(object l) |
|||
printf(1,"%v -> %v\n", {l, bind(bind(l,times_five),plus_four)}) |
|||
end procedure |
|||
test(3) |
|||
test("none")</lang> |
|||
{{out}} |
|||
<pre> |
|||
3 -> 19 |
|||
"none" -> "none" |
|||
</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>. |
|||
<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)</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> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|Rakudo|2019.11}} |
{{works with|Rakudo|2019.11}} |
||
It is exceptionally difficult to come up with a compelling valuable use for |
It is exceptionally difficult to come up with a compelling valuable use for |
||
Line 963: | Line 1,044: | ||
WAT Nothing Nothing Nothing Nothing |
WAT Nothing Nothing Nothing Nothing |
||
4.285714 0.233333 2.0701966780270626 1.455287232606842 -0.727643616303421</pre> |
4.285714 0.233333 2.0701966780270626 1.455287232606842 -0.727643616303421</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. |
|||
<lang Phix>function bind(object m, integer f) |
|||
return f(m) |
|||
end function |
|||
function unit(object m) |
|||
return m |
|||
end function |
|||
function times_five(object l) |
|||
return iff(integer(l)?l*5:l) |
|||
end function |
|||
function plus_four(object l) |
|||
return iff(integer(l)?l+4:l) |
|||
end function |
|||
procedure test(object l) |
|||
printf(1,"%v -> %v\n", {l, bind(bind(l,times_five),plus_four)}) |
|||
end procedure |
|||
test(3) |
|||
test("none")</lang> |
|||
{{out}} |
|||
<pre> |
|||
3 -> 19 |
|||
"none" -> "none" |
|||
</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>. |
|||
<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)</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> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |