Skip to content

Commit

Permalink
Add status checks and getters for AsyncResult
Browse files Browse the repository at this point in the history
  • Loading branch information
mlms13 committed Feb 12, 2019
1 parent b3c24ec commit 44d936c
Show file tree
Hide file tree
Showing 2 changed files with 240 additions and 39 deletions.
126 changes: 126 additions & 0 deletions __tests__/Relude_AsyncResult_test.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
open Jest;
open Expect;
module AsyncData = Relude_AsyncData;
module AsyncResult = Relude_AsyncResult;

describe("AsyncResult constructors", () => {
test("Init", () =>
expect(AsyncResult.init) |> toEqual(AsyncData.init)
);

test("Loading", () =>
expect(AsyncResult.loading) |> toEqual(AsyncData.loading)
);

test("Complete Ok", () =>
expect(AsyncResult.ok(1))
|> toEqual(AsyncData.complete(Belt.Result.Ok(1)))
);

test("Complete Error", () =>
expect(AsyncResult.error("Fail"))
|> toEqual(AsyncData.complete(Belt.Result.Error("Fail")))
);
});

describe("AsyncResult state checks", () => {
test("isOk when Loading", () =>
expect(AsyncResult.(loading |> isOk)) |> toEqual(false)
);

test("isOk when Reloading Ok", () =>
expect(AsyncResult.(reloadingOk(1) |> isOk)) |> toEqual(true)
);

test("isOk when Complete Ok", () =>
expect(AsyncResult.(ok(1) |> isOk)) |> toEqual(true)
);

test("isOk when Complete Error", () =>
expect(AsyncResult.(error("Fail") |> isOk)) |> toEqual(false)
);

test("isOk when Reloading Error", () =>
expect(AsyncResult.(reloadingError("Fail") |> isOk)) |> toEqual(false)
);

test("isError when Complete Error", () =>
expect(AsyncResult.(error("Fail") |> isError)) |> toEqual(true)
);

test("isError when Reloading Error", () =>
expect(AsyncResult.(reloadingError("Fail") |> isError)) |> toEqual(true)
);

test("isError when Reloading Ok", () =>
expect(AsyncResult.(reloadingOk(1) |> isError)) |> toEqual(false)
);

test("isError when Complete Ok", () =>
expect(AsyncResult.(ok(1) |> isError)) |> toEqual(false)
);

test("isCompleteOk when Complete Ok", () =>
expect(AsyncResult.(ok(1) |> isCompleteOk)) |> toEqual(true)
);

test("isCompleteOk when Reloading Ok", () =>
expect(AsyncResult.(reloadingOk(1) |> isCompleteOk)) |> toEqual(false)
);

test("isCompleteOk when Complete Error", () =>
expect(AsyncResult.(error("fail") |> isCompleteOk)) |> toEqual(false)
);

test("getOk when Reloading Ok", () =>
expect(AsyncResult.(reloadingOk(1) |> getOk)) |> toEqual(Some(1))
);

test("getOk when Complete Ok", () =>
expect(AsyncResult.(ok(1) |> getOk)) |> toEqual(Some(1))
);

test("getOk when Reloading Error", () =>
expect(AsyncResult.(reloadingError("fail") |> getOk)) |> toEqual(None)
);

test("getOk when Complete Error", () =>
expect(AsyncResult.(error("fail") |> getOk)) |> toEqual(None)
);

test("getCompleteOk when Reloading Ok", () =>
expect(AsyncResult.(reloadingOk(1) |> getCompleteOk)) |> toEqual(None)
);

test("getCompleteOk when Complete Ok", () =>
expect(AsyncResult.(ok(1) |> getCompleteOk)) |> toEqual(Some(1))
);

test("getError when Reloading Error", () =>
expect(AsyncResult.(reloadingError("fail") |> getError))
|> toEqual(Some("fail"))
);

test("getError when Complete Error", () =>
expect(AsyncResult.(error("fail") |> getError))
|> toEqual(Some("fail"))
);

test("getError when Reloading Ok", () =>
expect(AsyncResult.(reloadingOk(1) |> getError)) |> toEqual(None)
);

test("getError when Complete Ok", () =>
expect(AsyncResult.(ok(1) |> getError)) |> toEqual(None)
);

test("getCompleteError when Complete Error", () =>
expect(AsyncResult.(error("fail") |> getCompleteError))
|> toEqual(Some("fail"))
);

test("getCompleteError when Reloading Error", () =>
expect(AsyncResult.(reloadingError("fail") |> getCompleteError))
|> toEqual(None)
);
});
153 changes: 114 additions & 39 deletions src/Relude_AsyncResult.re
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
This type also implements map/apply/flatMap/etc. to operate on the innermost a value (inside the Result.Ok)
*/

/*******************************************************************************
* Type definition and constructors
******************************************************************************/
type t('a, 'e) = Relude_AsyncData.t(Belt.Result.t('a, 'e));

let init: t('a, 'e) = Relude_AsyncData.init;

let loading: t('a, 'e) = Relude_AsyncData.loading;

let reloadingOk: 'a => t('a, 'e) =
Expand All @@ -23,13 +25,14 @@ let completeError: 'e => t('a, 'e) =
e => Relude_AsyncData.complete(Belt.Result.Error(e));

/* Shortcuts */

let ok = completeOk;

let error = completeError;

let pure = ok;
/*******************************************************************************
* Needed by typeclasses
******************************************************************************/

let pure: 'a => t('a, 'e) = completeOk;
let map: ('a => 'b, t('a, 'e)) => t('b, 'e) =
(f, fa) =>
switch (fa) {
Expand Down Expand Up @@ -107,40 +110,112 @@ let bind: (t('a, 'e), 'a => t('b, 'e)) => t('b, 'e) =
| Complete(Error(_)) as r => r
};

let flatMap: ('a => t('b, 'e), t('a, 'e)) => t('b, 'e) = (f, fa) => bind(fa, f);

module type FUNCTOR_F = (E: BsAbstract.Interface.TYPE) => BsAbstract.Interface.FUNCTOR with type t('a) = t('a, E.t);

module Functor: FUNCTOR_F = (E: BsAbstract.Interface.TYPE) => {
type nonrec t('a) = t('a, E.t);
let map = map;
}

module type APPLY_F = (E: BsAbstract.Interface.TYPE) => BsAbstract.Interface.APPLY with type t('a) = t('a, E.t);

module Apply: APPLY_F = (E: BsAbstract.Interface.TYPE) => {
include Functor(E);
let apply = apply;
}

module ApplyFunctions = (E: BsAbstract.Interface.TYPE) => BsAbstract.Functions.Apply(Apply(E));

module type APPLICATIVE_F = (E: BsAbstract.Interface.TYPE) => BsAbstract.Interface.APPLICATIVE with type t('a) = t('a, E.t);

module Applicative: APPLICATIVE_F = (E: BsAbstract.Interface.TYPE) => {
include Apply(E);
let pure = pure;
}

module type MONAD_F = (E: BsAbstract.Interface.TYPE) => BsAbstract.Interface.MONAD with type t('a) = t('a, E.t);

module Monad: MONAD_F = (E: BsAbstract.Interface.TYPE) => {
include Applicative(E);
let flat_map = bind;
}
let flatMap: ('a => t('b, 'e), t('a, 'e)) => t('b, 'e) =
(f, fa) => bind(fa, f);

/*******************************************************************************
* Utilities specific to this type
******************************************************************************/

let isInit = Relude_AsyncData.isInit;
let isBusy = Relude_AsyncData.isBusy;
let isLoading = Relude_AsyncData.isLoading;
let isReloading = Relude_AsyncData.isReloading;
let isComplete = Relude_AsyncData.isComplete;

let isOk: 'a 'e. t('a, 'e) => bool =
fun
| Complete(Ok(_))
| Reloading(Ok(_)) => true
| _ => false;

let isError: 'a 'e. t('a, 'e) => bool =
fun
| Complete(Error(_))
| Reloading(Error(_)) => true
| _ => false;

let isCompleteOk: 'a 'e. t('a, 'e) => bool =
fun
| Complete(Ok(_)) => true
| _ => false;

let isCompleteError: 'a 'e. t('a, 'e) => bool =
fun
| Complete(Error(_)) => true
| _ => false;

let getOk: 'a 'e. t('a, 'e) => option('a) =
fun
| Complete(Ok(v))
| Reloading(Ok(v)) => Some(v)
| _ => None;

let getError: 'a 'e. t('a, 'e) => option('e) =
fun
| Complete(Error(x))
| Reloading(Error(x)) => Some(x)
| _ => None;

let getCompleteOk: 'a 'e. t('a, 'e) => option('a) =
fun
| Complete(Ok(v)) => Some(v)
| _ => None;

let getCompleteError: 'a 'e. t('a, 'e) => option('e) =
fun
| Complete(Error(x)) => Some(x)
| _ => None;

/*******************************************************************************
* Typeclass implementations
******************************************************************************/

module type FUNCTOR_F =
(E: BsAbstract.Interface.TYPE) =>
BsAbstract.Interface.FUNCTOR with type t('a) = t('a, E.t);

module Functor: FUNCTOR_F =
(E: BsAbstract.Interface.TYPE) => {
type nonrec t('a) = t('a, E.t);
let map = map;
};

module type APPLY_F =
(E: BsAbstract.Interface.TYPE) =>
BsAbstract.Interface.APPLY with type t('a) = t('a, E.t);

module Apply: APPLY_F =
(E: BsAbstract.Interface.TYPE) => {
include Functor(E);
let apply = apply;
};

module ApplyFunctions = (E: BsAbstract.Interface.TYPE) =>
BsAbstract.Functions.Apply((Apply(E)));

module type APPLICATIVE_F =
(E: BsAbstract.Interface.TYPE) =>
BsAbstract.Interface.APPLICATIVE with type t('a) = t('a, E.t);

module Applicative: APPLICATIVE_F =
(E: BsAbstract.Interface.TYPE) => {
include Apply(E);
let pure = pure;
};

module type MONAD_F =
(E: BsAbstract.Interface.TYPE) =>
BsAbstract.Interface.MONAD with type t('a) = t('a, E.t);

module Monad: MONAD_F =
(E: BsAbstract.Interface.TYPE) => {
include Applicative(E);
let flat_map = bind;
};

module Infix = (E: BsAbstract.Interface.TYPE) => {
module Functor = BsAbstract.Infix.Functor(Functor(E));
module Apply = BsAbstract.Infix.Apply(Apply(E));
module Monad = BsAbstract.Infix.Monad(Monad(E));
}
module Functor = BsAbstract.Infix.Functor((Functor(E)));
module Apply = BsAbstract.Infix.Apply((Apply(E)));
module Monad = BsAbstract.Infix.Monad((Monad(E)));
};

0 comments on commit 44d936c

Please sign in to comment.