-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathgeneric_util_applicative.ml
More file actions
63 lines (50 loc) · 1.46 KB
/
Copy pathgeneric_util_applicative.ml
File metadata and controls
63 lines (50 loc) · 1.46 KB
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
(** Applicative functors. *)
open Generic_util
open App.T
open App
open Monoid.T
module T = struct
type 'f applicative =
{ pure : 'a . 'a -> ('a,'f) app
; apply : 'a 'b . ('a -> 'b, 'f) app -> ('a, 'f) app -> ('b, 'f) app
}
end
include T
type 'f t = 'f applicative
(** {2 Operations} *)
let fun_of_app {pure; apply} =
{Functor.fmap = fun f -> apply (pure f)}
let liftA a f x = (fun_of_app a).fmap f x
let liftA2 a f x y = a.apply (liftA a f x) y
let liftA3 a f x y z = a.apply (liftA2 a f x y) z
let liftA4 a f u v w x = a.apply (liftA3 a f u v w) x
(** {3 Traversing lists of effectful elements } *)
let rec traverse a f =
let cons h t = h :: t in function
| [] -> a.pure []
| h :: t -> liftA2 a cons (f h) (traverse a f t)
let sequence a = traverse a (fun x -> x)
(** {2 Instances} *)
let id =
{ pure = (fun x -> Id x)
; apply = (fun f x -> Id ((get_id f) (get_id x)))
}
let const {mempty;mappend} =
{ pure = (fun _ -> Const mempty)
; apply = (fun f x -> Const (mappend (get_const f) (get_const x)))
}
let option =
let option_apply f x = match f , x with
| Some f , Some x -> Some (f x)
| _ -> None
in
{ pure = (fun x -> Option (Some x))
; apply = (fun fs xs -> Option (option_apply (get_option fs) (get_option xs)))
}
let list =
let list_apply fs xs =
List.concat (List.map (fun f -> List.map f xs) fs)
in
{ pure = (fun x -> List [x])
; apply = (fun fs xs -> List (list_apply (get_list fs) (get_list xs)))
}