From 67d6fb1ce37c1f2f0bd57f2fd62bf31d2d94cde3 Mon Sep 17 00:00:00 2001 From: "Victor Wang(wang shaojie)" Date: Tue, 11 Sep 2018 19:09:43 +0800 Subject: [PATCH 1/2] add create, filter_opt, reduce, merge for RList --- __tests__/RList_test.re | 26 ++++++++++++++++++++++++- src/RList.re | 42 ++++++++++++++++++++++++++++++++++++++++- src/RList.rei | 10 +++++++++- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/__tests__/RList_test.re b/__tests__/RList_test.re index 1ceccdc..5f57343 100644 --- a/__tests__/RList_test.re +++ b/__tests__/RList_test.re @@ -278,4 +278,28 @@ test("difference", () => expect(difference([1, 2, 3], [3, 4, 5])) |> toEqual([1, test("intersection", () => expect(intersection([1, 2, 3], [3, 4, 5])) |> toEqual([3])); -test("zip", () => expect(zip([1, 2, 3], [4, 5, 6])) |> toEqual([(1, 4), (2, 5), (3, 6)])); \ No newline at end of file +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/RList.re b/src/RList.re index 2b52536..b4a819c 100644 --- a/src/RList.re +++ b/src/RList.re @@ -353,4 +353,44 @@ let filter_map = (pred, f, xs) => let filter_mapi = (pred, f, xs) => fold_lefti((acc, i, a) => pred(i, a) ? append(f(i, a), acc) : acc, [], xs); -let pure = (a) => [a]; \ No newline at end of file +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); +}; \ No newline at end of file diff --git a/src/RList.rei b/src/RList.rei index 5992525..ac8073a 100644 --- a/src/RList.rei +++ b/src/RList.rei @@ -149,4 +149,12 @@ 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); \ No newline at end of file +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); \ No newline at end of file From 8ea0fa6f2d14eac60d1212cf1c34febd759a7b05 Mon Sep 17 00:00:00 2001 From: "Victor Wang(wang shaojie)" Date: Sun, 23 Sep 2018 20:03:05 +0800 Subject: [PATCH 2/2] create tryWith for Option --- __tests__/Option_test.re | 6 +++++- src/Option.re | 5 +++++ src/Option.rei | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/__tests__/Option_test.re b/__tests__/Option_test.re index 1f3915e..9b8ef6e 100644 --- a/__tests__/Option_test.re +++ b/__tests__/Option_test.re @@ -86,4 +86,8 @@ describe( } ) } -); \ No newline at end of file +); + +test("tryWith", () => expect((tryWith(() => raise(Not_found)), tryWith(() => 3))) + |> toEqual((None, Some(3))) +) \ 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);