aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/monad.ml
diff options
context:
space:
mode:
authorGravatar Arnaud Spiwack <arnaud@spiwack.net>2014-10-17 17:43:38 +0200
committerGravatar Arnaud Spiwack <arnaud@spiwack.net>2014-10-22 07:31:45 +0200
commit000c1e636b033c57fc070d323140f9e26296b9c0 (patch)
tree66c92e5bf9f10288fc35e12b88c19cd5d263ff4b /lib/monad.ml
parentd5fec4d21f1dcc8790b52a2b299a05f1e1f32eab (diff)
Small optimisation in the monadic list combinators.
The monadic bind can be costly, so sparing a few can be worth it. Therefore I unrolled the last element of the recursions. I took the opportunity to do some loop unrolling, which is probably more useful for map combinators than for fold.
Diffstat (limited to 'lib/monad.ml')
-rw-r--r--lib/monad.ml31
1 files changed, 24 insertions, 7 deletions
diff --git a/lib/monad.ml b/lib/monad.ml
index 78cf929d2..b165ffbfb 100644
--- a/lib/monad.ml
+++ b/lib/monad.ml
@@ -70,32 +70,49 @@ module Make (M:Def) : S with type +'a t = 'a M.t = struct
module List = struct
+ (* The combinators are loop-unrolled to spare a some monadic binds
+ (it is a common optimisation to treat the last of a list of
+ bind specially) and hopefully gain some efficiency using fewer
+ jump. *)
+
let rec map f = function
| [] -> return []
- | a::l ->
+ | [a] ->
+ f a >>= fun a' ->
+ return [a']
+ | a::b::l ->
f a >>= fun a' ->
+ f b >>= fun b' ->
map f l >>= fun l' ->
- return (a'::l')
+ return (a'::b'::l')
let rec map_right f = function
| [] -> return []
- | a::l ->
+ | [a] ->
+ f a >>= fun a' ->
+ return [a']
+ | a::b::l ->
map f l >>= fun l' ->
+ f b >>= fun b' ->
f a >>= fun a' ->
- return (a'::l')
+ return (a'::b'::l')
let rec fold_right f l x =
match l with
| [] -> return x
- | a::l ->
+ | [a] -> f a x
+ | a::b::l ->
fold_right f l x >>= fun acc ->
+ f b acc >>= fun acc ->
f a acc
let rec fold_left f x = function
| [] -> return x
- | a::l ->
+ | [a] -> f x a
+ | a::b::l ->
f x a >>= fun x' ->
- fold_left f x' l
+ f x' b >>= fun x'' ->
+ fold_left f x'' l
end
end