### 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: