diff --git a/__tests__/Option_test.re b/__tests__/Option_test.re index 5cb3e7d..5f917e8 100644 --- a/__tests__/Option_test.re +++ b/__tests__/Option_test.re @@ -77,4 +77,8 @@ describe("Functor", () => { let g = x => x + 3; expect(Some(0) <$> (f <|| g)) |> toEqual(Some(0) <$> g <$> f); }); -}); + test("tryWith", () => + expect((tryWith(() => raise(Not_found)), tryWith(() => 3))) + |> toEqual((None, Some(3))) + ); +}); \ No newline at end of file diff --git a/__tests__/RList_test.re b/__tests__/RList_test.re index 3989c35..a9fd8e6 100644 --- a/__tests__/RList_test.re +++ b/__tests__/RList_test.re @@ -321,3 +321,27 @@ test("zip", () => expect(zip([1, 2, 3], [4, 5, 6])) |> toEqual([(1, 4), (2, 5), (3, 6)]) ); + +test("create", () => + expect((create(x => x, -1), create(x => x * 2, 4))) + |> toEqual(([], [0, 2, 4, 6])) +); + +test("filter_opt", () => + expect(( + filter_opt([]), + filter_opt([Some(3), None, Some(4), None, Some(5)]), + )) + |> toEqual(([], [3, 4, 5])) +); + +test("reduce", () => + expect((reduce((+), []), reduce((+), [1, 2, 3]))) + |> toEqual((None, Some(6))) +); + +test("merge", () => { + let compare = (a, b) => a - b; + expect((merge(compare, [], []), merge(compare, [1, 3, 5], [2, 4]))) + |> toEqual(([], [1, 2, 3, 4, 5])); +}); \ No newline at end of file diff --git a/src/Option.re b/src/Option.re index fea6c8e..656e972 100644 --- a/src/Option.re +++ b/src/Option.re @@ -40,6 +40,11 @@ let firstSome = (a, b) => | _ => a }; +let tryWith = f => + try (Some(f())) { + | _ => None + }; + include Monad.MakeBasic({ type t('a) = option('a); let bind = (o, f) => diff --git a/src/Option.rei b/src/Option.rei index d8b7379..f7df4dc 100644 --- a/src/Option.rei +++ b/src/Option.rei @@ -14,6 +14,8 @@ let toExn: (string, option('a)) => 'a; let firstSome: (option('a), option('a)) => option('a); +let tryWith: (unit => 'a) => option('a); + include Monad.Basic with type t('a) := option('a); include Applicative.Basic with type t('a) := option('a); diff --git a/src/RList.re b/src/RList.re index b6c40ab..ba2e0f1 100644 --- a/src/RList.re +++ b/src/RList.re @@ -387,4 +387,45 @@ let filter_mapi = (pred, f, xs) => xs, ); -let pure = a => [a]; +let pure = (a) => [a]; + +let create = (f, n) => + if (n < 0) { + []; + } else { + let rec loop = (n, acc) => + n == 0 ? acc : loop(n - 1, [f(n - 1), ...acc]); + loop(n, []); + }; + +let filter_opt = xs => { + let rec loop = (l, acc) => + switch (l) { + | [] => acc + | [hd, ...tl] => + switch (hd) { + | None => loop(tl, acc) + | Some(x) => loop(tl, [x, ...acc]) + } + }; + List.rev(loop(xs, [])); +}; + +let reduce = (f, xs) => + switch (xs) { + | [] => None + | [hd, ...tl] => Some(List.fold_left(f, hd, tl)) + }; + +let merge = (compare, xs, ys) => { + let rec loop = (acc, xs, ys) => + switch (xs, ys) { + | ([], ys) => List.rev_append(acc, ys) + | (xs, []) => List.rev_append(acc, xs) + | ([h1, ...t1], [h2, ...t2]) => + compare(h1, h2) <= 0 ? + loop([h1, ...acc], t1, ys) : loop([h2, ...acc], xs, t2) + }; + loop([], xs, ys); +}; + diff --git a/src/RList.rei b/src/RList.rei index ec9016a..baf3a47 100644 --- a/src/RList.rei +++ b/src/RList.rei @@ -150,3 +150,11 @@ let filteri: ((int, 'a) => bool, list('a)) => list('a); let filter_map: ('a => bool, 'a => 'b, list('a)) => list('b); let filter_mapi: ((int, 'a) => bool, (int, 'a) => 'b, list('a)) => list('b); + +let create: (int => 'a, int) => list('a); + +let filter_opt: list(option('a)) => list('a); + +let reduce: (('a, 'a) => 'a, list('a)) => option('a); + +let merge: (('a, 'a) => int, list('a), list('a)) => list('a);