-
Notifications
You must be signed in to change notification settings - Fork 2
/
Monad.re
49 lines (43 loc) · 1.29 KB
/
Monad.re
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
module type Monad = {
open Applicative;
type t('a);
include Applicative with type t('a) := t('a);
let bind: (t('a), 'a => t('b)) => t('b);
};
module MonadUtils = (M: Monad) => {
open Base;
include M;
module AppU = Applicative.ApplicativeUtils(M);
include (AppU :(module type of AppU) with type t('a) := AppU.t('a));
let return = pure;
let (>>=) = bind;
let (=<<) = (f, m) => flip(bind, f, m);
let join = m => id =<< m;
let (>>) = (m, k) => m >>= const(k);
let (<<) = (m,k) => flip((>>), m, k);
let (>=>) = (f, g, x) => f(x) >>= g;
let (<=<) = (f, g, x) => f =<< g(x);
};
module MonadLaws = (M: Monad) => {
module MonadU = MonadUtils(M);
open MonadU;
let leftIdLaw = (f, x) => return(x) >>= f == f(x);
let rightIdLaw = x => x >>= return == x;
let associativityLaw = (m, f, g) =>
m >>= (x => f(x) >>= g) == (m >>= f >>= g);
};
module ListM_: Monad with type t('a) = list('a) = {
include Applicative.ListApplicative;
let bind = (m, f) =>
List.fold_right((x, y) => List.append(f(x), y), m, []);
};
module ListMonad = MonadUtils(ListM_);
module OptionM_: Monad with type t('a) = option('a) = {
include Applicative.OptionApplicative;
let bind = (m, f) =>
switch (m) {
| None => None
| Some(x) => f(x)
};
};
module OptionMonad = MonadUtils(OptionM_);