Skip to content

Search content

From F# to Gleam > 5: Option, Result, and Typed Errors

3 min readFrom F# to GleamPart 5
A parser branches into Ok with a check mark or Error with a named validation failure.

F# already gives us the vocabulary for missing values and expected failures: Option and Result. Gleam keeps both, with one small ecosystem difference. Many standard library lookups return Result(value, Nil) even when F# would commonly use an option.

Table of contents

On this page

Optional Data

Use an option when absence is an ordinary part of the model:

let greet name =
    match name with
    | Some value -> "Hello, " + value
    | None -> "Hello, guest"scratch.fsx

Option belongs to Gleam’s standard library and needs importing. Result, Ok, and Error are built in:

import gleam/int
import gleam/option.{type Option, None, Some}

fn greet(name: Option(String)) -> String {
  case name {
    Some(value) -> "Hello, " <> value
    None -> "Hello, guest"
  }
}src/learning_gleam.gleam

There isn’t an implicit null hiding inside String. If a name may be absent, put that possibility in its type.

Give Failures Useful Names

A quantity can fail because it isn’t an integer or because it isn’t positive. Those are different problems, so give them different variants:

type QuantityError = NotAnInteger | NotPositive

let parseQuantity (text: string) =
    match System.Int32.TryParse text with
    | true, value when value > 0 -> Ok value
    | true, _ -> Error NotPositive
    | false, _ -> Error NotAnIntegerscratch.fsx

Gleam’s int.parse returns Result(Int, Nil). A case expression can turn its unspecific failure into our domain error:

pub type QuantityError {
  NotAnInteger
  NotPositive
}

fn parse_quantity(text: String) -> Result(Int, QuantityError) {
  case int.parse(text) {
    Error(Nil) -> Error(NotAnInteger)
    Ok(value) if value > 0 -> Ok(value)
    Ok(_) -> Error(NotPositive)
  }
}src/learning_gleam.gleam

The return type documents both the successful value and the possible errors. These examples express the same validation stages, not identical numeric ranges or parser grammars. F#‘s int is a 32-bit integer, while Gleam’s integer representation depends on its target.

Decide at the Boundary

A user-facing caller can now choose a useful message by matching Ok(quantity), Error(NotAnInteger), or Error(NotPositive). Lower-level code doesn’t need to print an error or invent a fallback quantity.

For independent transformations, result.map changes a successful value, and result.map_error changes the error type. To chain an operation that can itself fail, use result.try. That’s the role filled by Result.bind in F#.

Gleam doesn’t provide try/catch syntax for normal error handling. That doesn’t mean programs can’t crash. panic, failed assertions, and foreign code can still fail at runtime. Keep expected bad input in a Result rather than turning it into a crash.

Try It

Combine the Gleam blocks in src/learning_gleam.gleam and run gleam run:

pub fn main() -> Nil {
  assert greet(Some("Ada")) == "Hello, Ada"
  assert greet(None) == "Hello, guest"
  assert parse_quantity("12") == Ok(12)
  assert parse_quantity("0") == Error(NotPositive)
  assert parse_quantity("-2") == Error(NotPositive)
  assert parse_quantity("twelve") == Error(NotAnInteger)
  assert parse_quantity("") == Error(NotAnInteger)
}src/learning_gleam.gleam

The same cases can follow the F# definitions:

assert (greet (Some "Ada") = "Hello, Ada")
assert (greet None = "Hello, guest")
assert (parseQuantity "12" = Ok 12)
assert (parseQuantity "0" = Error NotPositive)
assert (parseQuantity "-2" = Error NotPositive)
assert (parseQuantity "twelve" = Error NotAnInteger)
assert (parseQuantity "" = Error NotAnInteger)scratch.fsx

These assertions check known examples. In application code, don’t use let assert Ok(value) = ... on untrusted input. It crashes on an error rather than handling it.

Further reading: gleam/option and gleam/result.



Previous in series
From F# to Gleam > 4: Lists, Dictionaries, and Eager Transformations
Next in series
From F# to Gleam > 6: From Computation Expressions to use