⚠️ Oops! This page doesn't appear to define a type called _.

Using Belt.Result

Belt.Result defines a data type with two variants: Ok and Error. Each of these variants can contain data, and those two pieces of data need not have the same data type. Belt.Result is useful when you need to not only determine whether some data is valid or not (use Belt.Option for that), but also keep information about the invalid data.

In the examples, we presume the existence of two variables:

let good = Belt.Result.Ok(64)
let bad = Belt.Result.Error("Invalid data")
[@@@ocaml.ppx.context { cookies = [] }]
let good = ((Belt.Result.Ok (64))[@explicit_arity ])
let bad =
  ((Belt.Result.Error
      ((("Invalid data")[@reason.raw_literal "Invalid data"])))[@explicit_arity
                                                                 ])

Here are the functions that Belt.Result supports.

getExn

Retrieve the value in an Ok(n) result.

Sample call: getExn(res)

When res is of the form Ok(n), returns n When res is of the form Error(e), raise an exception

Js.log(Belt.Result.getExn(good)); /* 64 */
Js.log(Belt.Result.getExn(bad)); /* raises exception */
[@@@ocaml.ppx.context { cookies = [] }]
let good = ((Belt.Result.Ok (64))[@explicit_arity ])
let bad =
  ((Belt.Result.Error
      ((("Invalid data")[@reason.raw_literal "Invalid data"])))[@explicit_arity
                                                                 ])
let _ = Js.log (Belt.Result.getExn good)
let _ = Js.log (Belt.Result.getExn bad)

getWithDefault

Retrieve the value in an Ok(n) result, or provide a default if it is an Error(e).

Sample call: getWithDefault(res, default)

If res is Ok(n), returns n, otherwise default

Js.log(Belt.Result.getWithDefault(Ok(42), 0)); /* 42 */
Js.log(Belt.Result.getWithDefault(Error("Invalid Data"), 0)); /* 0 */
[@@@ocaml.ppx.context { cookies = [] }]
let _ = Js.log (Belt.Result.getWithDefault ((Ok (42))[@explicit_arity ]) 0)
let _ =
  Js.log
    (Belt.Result.getWithDefault
       ((Error ((("Invalid Data")[@reason.raw_literal "Invalid Data"])))
       [@explicit_arity ]) 0)

mapWithDefault

This function allows you to pass a Belt.Result argument to a function that has a non-Result parameter and returns a non-Result value. The result of mapWithDefault will be a non-Result value.

Sample call: mapWithDefault(res, default, f)

When res is of the form Ok(n), returns f(n), otherwise default.

let half = (x) => x / 2
Js.log(Belt.Result.mapWithDefault(good, 0,half)); /* 32 */
Js.log(Belt.Result.mapWithDefault(bad, 0, half)); /* 0 */
[@@@ocaml.ppx.context { cookies = [] }]
let good = ((Belt.Result.Ok (64))[@explicit_arity ])
let bad =
  ((Belt.Result.Error
      ((("Invalid data")[@reason.raw_literal "Invalid data"])))[@explicit_arity
                                                                 ])
let half x = x / 2
let _ = Js.log (Belt.Result.mapWithDefault good 0 half)
let _ = Js.log (Belt.Result.mapWithDefault bad 0 half)

map

This function allows you to pass a Belt.Result argument to a function that has a non-Result parameter and return value. The result of map will be a Belt.Result value.

Sample call: map(res, f)

When res is of the formOk(n), returns Ok(f(n)). Otherwise returns res unchanged. Function f takes a value of the same type as n and returns a non-Result value.

let f = (x) => sqrt(float_of_int(x));

Js.log(Belt.Result.map(Ok(64), f)); /* Ok(8.0) */
Js.log(Belt.Result.map(Error("Invalid"), f)); /* Error("Invalid") */
[@@@ocaml.ppx.context { cookies = [] }]
let good = ((Belt.Result.Ok (64))[@explicit_arity ])
let bad =
  ((Belt.Result.Error
      ((("Invalid data")[@reason.raw_literal "Invalid data"])))[@explicit_arity
                                                                 ])
let f x = sqrt (float_of_int x)
let _ = Js.log (Belt.Result.map ((Ok (64))[@explicit_arity ]) f)
let _ =
  Js.log
    (Belt.Result.map
       ((Error ((("Invalid")[@reason.raw_literal "Invalid"])))[@explicit_arity
                                                                ]) f)

flatMap

This function allows you to pass a Belt.Result argument to a function that has a non-Result parameter and returns a Belt.Result value.

Sample call: flatMap(res, f)

When res is Ok(n), returns f(n). Otherwise, returns res unchanged.

Function f takes a value of the same type as n and returns a Belt.Result.

let reciprocal = (x) => {
  if (x != 0.0) {
    Belt.Result.Ok(1.0 /. x)
  } else {
    Belt.Result.Error("Divide by zero");
  }
};
  
Js.log(Belt.Result.flatMap(Ok(2.0), reciprocal)); /* Ok(0.5) */
Js.log(Belt.Result.flatMap(Ok(0.0), reciprocal)); /* Error("Divide by zero") */
Js.log(Belt.Result.flatMap(Error("Already bad"),
  reciprocal)); /* Error("Already bad")) */
[@@@ocaml.ppx.context { cookies = [] }]
let reciprocal x =
  if x <> 0.0
  then ((Belt.Result.Ok ((1.0 /. x)))[@explicit_arity ])
  else
    ((Belt.Result.Error
        ((("Divide by zero")[@reason.raw_literal "Divide by zero"])))
    [@explicit_arity ])
let _ =
  Js.log (Belt.Result.flatMap ((Ok (2.0))[@explicit_arity ]) reciprocal)
let _ =
  Js.log (Belt.Result.flatMap ((Ok (0.0))[@explicit_arity ]) reciprocal)
let _ =
  Js.log
    (Belt.Result.flatMap
       ((Error ((("Already bad")[@reason.raw_literal "Already bad"])))
       [@explicit_arity ]) reciprocal)

isOk

Sample call: isOk(res)

Returns true if res is of the form Ok(n), false if it is the Error(e) variant.

Js.log(Belt.Result.isOk(good)); /* true */
Js.log(Belt.Result.isOk(bad)); /* false */
[@@@ocaml.ppx.context { cookies = [] }]
let good = ((Belt.Result.Ok (64))[@explicit_arity ])
let bad =
  ((Belt.Result.Error
      ((("Invalid data")[@reason.raw_literal "Invalid data"])))[@explicit_arity
                                                                 ])
let _ = Js.log (Belt.Result.isOk good)
let _ = Js.log (Belt.Result.isOk bad)

isError

Sample call: isError(res)

Returns true if res is of the form Error(e), false if it is the Ok(n) variant.

Js.log(Belt.Result.isError(good)); /* false */
Js.log(Belt.Result.isError(bad)); /* true */
[@@@ocaml.ppx.context { cookies = [] }]
let good = ((Belt.Result.Ok (64))[@explicit_arity ])
let bad =
  ((Belt.Result.Error
      ((("Invalid data")[@reason.raw_literal "Invalid data"])))[@explicit_arity
                                                                 ])
let _ = Js.log (Belt.Result.isError good)
let _ = Js.log (Belt.Result.isError bad)

eq

Determine if two Belt.Result variables are equal with respect to an equality function.

Sample call: eq(res1, res2, f)

let good1 = Belt.Result.Ok(42);
let good2 = Belt.Result.Ok(32);
let bad1 = Belt.Result.Error("invalid");
let bad2 = Belt.Result.Error("really invalid");

let mod10equal = (a, b) => {
  a mod 10 == b mod 10
};

Js.log(Belt.Result.eq(good1, good2, mod10equal)); /* true */
Js.log(Belt.Result.eq(good1, bad1, mod10equal)); /* false */
Js.log(Belt.Result.eq(bad2, good2, mod10equal)); /* false */
Js.log(Belt.Result.eq(bad1, bad2, mod10equal)); /* true */
[@@@ocaml.ppx.context { cookies = [] }]
let good1 = ((Belt.Result.Ok (42))[@explicit_arity ])
let good2 = ((Belt.Result.Ok (32))[@explicit_arity ])
let bad1 =
  ((Belt.Result.Error ((("invalid")[@reason.raw_literal "invalid"])))
  [@explicit_arity ])
let bad2 =
  ((Belt.Result.Error
      ((("really invalid")[@reason.raw_literal "really invalid"])))[@explicit_arity
                                                                    ])
let mod10equal a b = (a mod 10) = (b mod 10)
let _ = Js.log (Belt.Result.eq good1 good2 mod10equal)
let _ = Js.log (Belt.Result.eq good1 bad1 mod10equal)
let _ = Js.log (Belt.Result.eq bad2 good2 mod10equal)
let _ = Js.log (Belt.Result.eq bad1 bad2 mod10equal)

cmp

Compare two Belt.Result variables with respect to a comparison function.

Sample call: cmp(res1, res2, f)

The comparison function returns -1 if the first variable is "less than" the second, 0 if the two variables are equal, and 1 if the first is "greater than" the second.

let mod10cmp = (a, b) => {
  Pervasives.compare((a mod 10), (b mod 10))
};

Js.log(Belt.Result.cmp(Ok(39), Ok(57), mod10cmp)); /* 1 */
Js.log(Belt.Result.cmp(Ok(57), Ok(39), mod10cmp)); /* -1 */
Js.log(Belt.Result.cmp(Ok(39), Error("y"), mod10cmp)); /* 1 */
Js.log(Belt.Result.cmp(Error("x"), Ok(57), mod10cmp)); /* -1 */
Js.log(Belt.Result.cmp(Error("x"), Error("y"), mod10cmp)); /* 0 */
[@@@ocaml.ppx.context { cookies = [] }]
let mod10cmp a b = Pervasives.compare (a mod 10) (b mod 10)
let _ =
  Js.log
    (Belt.Result.cmp ((Ok (39))[@explicit_arity ])
       ((Ok (57))[@explicit_arity ]) mod10cmp)
let _ =
  Js.log
    (Belt.Result.cmp ((Ok (57))[@explicit_arity ])
       ((Ok (39))[@explicit_arity ]) mod10cmp)
let _ =
  Js.log
    (Belt.Result.cmp ((Ok (39))[@explicit_arity ])
       ((Error ((("y")[@reason.raw_literal "y"])))[@explicit_arity ])
       mod10cmp)
let _ =
  Js.log
    (Belt.Result.cmp
       ((Error ((("x")[@reason.raw_literal "x"])))[@explicit_arity ])
       ((Ok (57))[@explicit_arity ]) mod10cmp)
let _ =
  Js.log
    (Belt.Result.cmp
       ((Error ((("x")[@reason.raw_literal "x"])))[@explicit_arity ])
       ((Error ((("y")[@reason.raw_literal "y"])))[@explicit_arity ])
       mod10cmp)

Uncurried Versions of Functions

Some of the functions in this module have uncurried versions. In ReasonML, if you don’t provide all the arguments to a function, you get a new, partially-applied function (this is called “currying”). When you are interoperating with JavaScript, however, this can be a problem. If you don’t provide all the arguments, JavaScript can’t detect that at compile time. Instead, any missing argument problems will show up at runtime. See this page for more details

To solve this problem, the functions that have more than one parameter have uncurried versions. Their name ends with a capital U. They have the same arguments in the same order, but you must provide all the arguments when you call them. The uncurried-version functions are: