Skip to content

Instantly share code, notes, and snippets.

@Leonidas-from-XIV
Last active January 18, 2022 16:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Leonidas-from-XIV/8d54d2756458ac7569112035e7a6ec3d to your computer and use it in GitHub Desktop.
Save Leonidas-from-XIV/8d54d2756458ac7569112035e7a6ec3d to your computer and use it in GitHub Desktop.
A way to use the `let` operators to short-circuit a `fold`
(* Some kind of function that needs to be [Some _] for the rest of the body *)
let bigger_than x v = match v > x with true -> Some (v - 1) | false -> None
(* Sample inputs *)
let xs = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9 ]
(* Why `fold` here in the first place? Maybe your data structure doesn't have `filter_map` etc.
* This is an example
*)
(* the classic way is to match and evaluate to `acc` on every branch, nesting deeper and deeper *)
let classic xs =
List.fold_left
(fun acc x ->
match bigger_than 3 x with
| None -> acc
| Some condition1 -> (
match bigger_than condition1 x with
| None -> acc
| Some condition2 -> condition2 :: acc))
[] xs
let new_style xs =
List.fold_left
(fun acc x ->
(* instead, we define a custom operator that returns `acc` in the `None` case *)
let ( let* ) a f = match a with Some a -> f a | None -> acc in
let* condition1 = bigger_than 3 x in
let* condition2 = bigger_than condition1 x in
condition2 :: acc)
[] xs
(* of course the same is possible with operators like `>>=` but it is slightly more messy *)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment