### Inline functions with member constraints Code Snippet

1
2
3
4
5
6

let inline fmap f (x: ^t) =
(^t : (static member fmap : unit -> ((^a -> ^b) -> ^t -> ^c)) ()) f x
let inline liftA f (x: ^t) =
(^t : (static member liftA : unit -> (^a -> ^t -> ^b)) ()) f x
let inline liftM (x: ^t) f =
(^t : (static member liftM : unit -> (^t -> ^a -> ^b)) ()) x f

### Inline functions with member constraints Code output:

### Inline operators with member constraints Code Snippet

1
2
3

let inline (<@>) f m = fmap f m (* Sadly, <$> can't be used *)
let inline (<*>) fm m = liftA fm m
let inline (>>=) m f = liftM m f

### Inline operators with member constraints Code output:

### Maybe (Option) with fmap, liftA and liftM Code Snippet

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

type 'a Maybe = Just of 'a | Nothing
(* Functor *)
type 'a Maybe with
static member fmap () : ('a -> 'b) -> 'a Maybe -> 'b Maybe =
fun f -> function | Just x -> f x |> Just | Nothing -> Nothing
(* Applicative *)
type 'a Maybe with
static member liftA () : ('a -> 'b) Maybe -> 'a Maybe -> 'b Maybe =
fun fm ->
fun m ->
match fm,m with
| Just f, Just x -> f x |> Just
| ______________ -> Nothing
(* Monad *)
type 'a Maybe with
static member liftM () : 'a Maybe -> ('a -> 'b Maybe) -> 'b Maybe =
fun m ->
fun f ->
match m with
| Nothing -> Nothing
| Just x -> f x
(* Maybe with functions, the amount of parenthesis is to damn high *)
fmap ((+) 1) (Just 42);;
liftA (Just ((+) 1)) (Just 42);;
liftM (Just 42) (fun x -> x + 1 |> Just);;
(* Maybe with operators, fewer parenthesis *)
( (+) 1) <@> Just 42;;
Just ((+) 1) <*> Just 42;;
Just 42 >>= fun x -> x + 1 |> Just;;

### Maybe (Option) with fmap, liftA and liftM Code output:

### Vect (list) with fmap, liftA and liftM Code Snippet

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

(* A list in F# is just a type abbreviation of a FSharpList *)
typedefof<List<_>> = typedefof<_ list>
(* Functor *)
type 'a List with
static member fmap () : ('a -> 'b) -> 'a list -> 'b list = List.map
(* This works *)
List.fmap () ((+) 1) [ 0 .. 10 ]
(* but this doesn't *)
// fmap ((+) 1) <@> [ 42 ]
(* error FS0001: The type ''a list' does not support the operator 'fmap' *)
(* Therefore, lets create our own type wrapping native lists in a Vector *)
type 'a Vect = Vect of 'a list
(* Functor *)
type 'a Vect with
static member fmap () : ('a -> 'b) -> 'a Vect -> 'b Vect =
fun f ->
fun (Vect xs) ->
List.map f xs |> Vect
(* Applicative *)
type 'a Vect with
static member liftA () : ('a -> 'b) Vect -> 'a Vect -> 'b Vect =
fun (Vect fs) ->
fun (Vect xs) ->
fs
|> List.map (fun f -> xs |> List.map f)
|> List.concat |> Vect
(* Monad *)
type 'a Vect with
static member liftM () : 'a Vect -> ('a list -> 'b Vect) -> 'b Vect =
fun (Vect xs) ->
fun f ->
f xs
(* Vect with operators, fewer parenthesis *)
( (+) 1) <@> Vect [ 0 .. 5 ];;
Vect [ id; ((+) 1) ] <*> Vect [ 0 .. 5 ];;
Vect [ 0 .. 5 ] >>= fun xs -> xs |> List.map ((+) 1) |> Vect;;

### Vect (list) with fmap, liftA and liftM Code output:

### Result (Choice) with fmap, liftA and liftM Code Snippet

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

type ('error,'a) Result = Ok of 'a | Err of 'error
(* Functor *)
type ('c,'a) Result with
static member fmap () : ('a -> 'b) -> ('c,'a) Result -> ('c,'b) Result =
fun f -> function | Ok x -> f x |> Ok | Err e -> Err e
(* Applicative *)
type ('c,'a) Result with
static member liftA () :
('c,('a -> 'b)) Result -> ('c,'a) Result -> ('c,'b) Result =
fun fm ->
fun m ->
match fm,m with
| Ok f, Ok x -> f x |> Ok
| Err e, _
| _ , Err e -> Err e
(* Monad *)
type ('c,'a) Result with
static member liftM () :
('c,'a) Result -> ('a -> ('c,'b) Result) -> ('c,'b) Result =
fun m ->
fun f ->
match m with
| Err e -> Err e
| Ok x -> f x
(* Result with operators, fewer parenthesis *)
( ((+) 1) <@> Ok 42 : (exn,int) Result);;
( Ok ((+) 1) <*> Ok 42 : (exn,int) Result);;
( Ok 42 >>= (fun x -> x + 1 |> Ok) : (exn,int) Result);;

### Result (Choice) with fmap, liftA and liftM Code output:

### Combining Maybe and Result using (»=) Code Snippet

1
2
3
4
5
6
7
8
9
10
11

let inc x = x + 1
let incM x = inc x |> Just
let defM x = function | Just y -> y | Nothing -> x
let incR x = inc x |> Ok
let defR = function | Ok x -> x | Err e -> raise e
42
|> Just >>= incM >>= incM >>= incM >>= incM
|> defM 0
|> Ok >>= incR >>= incR >>= incR >>= incR
|> defR

### Combining Maybe and Result using (»=) Code output:

### References:

- You’ve reached Adit’s homepage:
- theburningmonk.com, Yan Cui’s blog: