View Source Funx.Monad.Maybe (funx v0.1.0)

The Funx.Monad.Maybe module provides an implementation of the Maybe monad, a functional abstraction used to represent optional values in Elixir.

A Maybe represents one of two possibilities:

  • Just(value): the presence of a value
  • Nothing: the absence of a value

This pattern is useful for eliminating nil checks and handling missing data explicitly and safely in functional pipelines.

Constructors

Refinement

  • just?/1: Returns true if the value is a Just.
  • nothing?/1: Returns true if the value is a Nothing.

Fallback and Extraction

  • get_or_else/2: Returns the value from a Just, or a default if Nothing.
  • or_else/2: Returns the original Just, or invokes a fallback function if Nothing.

List Operations

  • concat/1: Removes all Nothing values and unwraps the Just values from a list.
  • concat_map/2: Applies a function and collects only Just results.
  • sequence/1: Converts a list of Maybe values into a single Maybe of list.
  • traverse/2: Applies a function to each element in a list and sequences the results.

Lifting

  • lift_predicate/2: Converts a value to Just if it meets a predicate, otherwise Nothing.
  • lift_identity/1: Converts an Identity to a Maybe.
  • lift_either/1: Converts an Either to a Maybe.
  • lift_eq/1: Lifts an equality function for use in the Maybe context.
  • lift_ord/1: Lifts an ordering function for use in the Maybe context.

Elixir Interoperability

  • from_nil/1: Converts nil to Nothing, otherwise wraps the value in Just.
  • to_nil/1: Returns the underlying value or nil.
  • from_result/1: Converts {:ok, val} or {:error, _} into a Maybe.
  • to_result/1: Converts a Maybe to a result tuple.
  • from_try/1: Runs a function and returns Just on success, or Nothing if an exception is raised.
  • to_try!/2: Unwraps a Just, or raises an error if Nothing.

Protocols

The Just and Nothing structs implement the following protocols, making the Maybe abstraction composable and extensible:

  • Funx.Eq: Enables equality comparisons between Maybe values.
  • Funx.Foldable: Implements fold_l/3 and fold_r/3 for reducing over the value or fallback.
  • Funx.Filterable: Supports conditional retention with filter/2, guard/2, and filter_map/2.
  • Funx.Monad: Provides map/2, ap/2, and bind/2 for monadic composition.
  • Funx.Ord: Defines ordering behavior between Just and Nothing values.

Although these implementations are defined per constructor (Just and Nothing), the behavior is consistent across the Maybe abstraction.

This module helps you represent optional data explicitly, structure conditional logic safely, and eliminate reliance on nil in functional pipelines.

Summary

Functions

Removes Nothing values from a list of Maybe and returns a list of unwrapped Just values.

Maps a function over a list, collecting unwrapped Just values and ignoring Nothing in a single pass.

Converts nil to Nothing; any other value becomes Just.

Converts a result tuple to a Maybe. {:ok, value} becomes Just(value), while {:error, _} becomes Nothing.

Executes a function within a Maybe context, returning Nothing if an exception occurs.

Retrieves the value from a Maybe, returning default if Nothing.

Wraps a value in Just.

Returns true if the Maybe is Just, otherwise false.

Converts an Either to a Maybe. Right becomes Just, and Left becomes Nothing.

Lifts an equality function to compare Maybe values

Converts an Identity value into a Maybe. If the value is nil, returns Nothing; otherwise Just.

Adapts an ordering function to compare Maybe values

Lifts a value into Maybe based on a predicate. If predicate.(value) is true, returns Just(value); otherwise Nothing.

Returns a Nothing value.

Returns true if the Maybe is Nothing, otherwise false.

Returns the current Just value or invokes the fallback_fun if Nothing.

Alias for just/1.

Converts a list of Maybe values into a Maybe containing a list. If any element is Nothing, the entire result is Nothing.

Converts a Maybe to its wrapped value or nil.

Returns true if the given Maybe is a Just, or false if it is Nothing.

Converts a Maybe to a result tuple. Just(value) becomes {:ok, value}, while Nothing becomes {:error, :nothing}.

Extracts a value from a Maybe, raising an exception if Nothing.

Applies a function to each element of a list, collecting results into a single Maybe. If any call returns Nothing, the operation halts and returns Nothing.

Types

Functions

@spec concat([t(output)]) :: [output] when output: any()

Removes Nothing values from a list of Maybe and returns a list of unwrapped Just values.

Examples

iex> Funx.Monad.Maybe.concat([Funx.Monad.Maybe.pure(1), Funx.Monad.Maybe.nothing(), Funx.Monad.Maybe.pure(2)])
[1, 2]

iex> Funx.Monad.Maybe.concat([Funx.Monad.Maybe.nothing(), Funx.Monad.Maybe.nothing()])
[]

iex> Funx.Monad.Maybe.concat([Funx.Monad.Maybe.pure("a"), Funx.Monad.Maybe.pure("b"), Funx.Monad.Maybe.pure("c")])
["a", "b", "c"]
@spec concat_map([input], (input -> t(output))) :: [output]
when input: any(), output: any()

Maps a function over a list, collecting unwrapped Just values and ignoring Nothing in a single pass.

Examples

iex> Funx.Monad.Maybe.concat_map([1, 2, 3, 4], fn x ->
...>   if rem(x, 2) == 0, do: Funx.Monad.Maybe.pure(x), else: Funx.Monad.Maybe.nothing()
...> end)
[2, 4]

iex> Funx.Monad.Maybe.concat_map([1, nil, 3], fn
...>   nil -> Funx.Monad.Maybe.nothing()
...>   x -> Funx.Monad.Maybe.pure(x * 2)
...> end)
[2, 6]

iex> Funx.Monad.Maybe.concat_map([1, 2, 3], fn x -> Funx.Monad.Maybe.pure(x + 1) end)
[2, 3, 4]

iex> Funx.Monad.Maybe.concat_map([], fn x -> Funx.Monad.Maybe.pure(x) end)
[]
@spec from_nil(nil | value) :: t(value) when value: term()

Converts nil to Nothing; any other value becomes Just.

Examples

iex> Funx.Monad.Maybe.from_nil(nil)
%Funx.Monad.Maybe.Nothing{}

iex> Funx.Monad.Maybe.from_nil(5)
%Funx.Monad.Maybe.Just{value: 5}
@spec from_result({:ok, right} | {:error, term()}) :: t(right) when right: term()

Converts a result tuple to a Maybe. {:ok, value} becomes Just(value), while {:error, _} becomes Nothing.

Examples

iex> Funx.Monad.Maybe.from_result({:ok, 5})
%Funx.Monad.Maybe.Just{value: 5}

iex> Funx.Monad.Maybe.from_result({:error, :something})
%Funx.Monad.Maybe.Nothing{}
@spec from_try((-> right)) :: t(right) when right: term()

Executes a function within a Maybe context, returning Nothing if an exception occurs.

Examples

iex> Funx.Monad.Maybe.from_try(fn -> 5 end)
%Funx.Monad.Maybe.Just{value: 5}

iex> Funx.Monad.Maybe.from_try(fn -> raise "error" end)
%Funx.Monad.Maybe.Nothing{}
Link to this function

get_or_else(maybe, default)

View Source
@spec get_or_else(t(value), value) :: value when value: var

Retrieves the value from a Maybe, returning default if Nothing.

Examples

iex> Funx.Monad.Maybe.get_or_else(Funx.Monad.Maybe.just(5), 0)
5

iex> Funx.Monad.Maybe.get_or_else(Funx.Monad.Maybe.nothing(), 0)
0
@spec just(any()) :: Funx.Monad.Maybe.Just.t(any())

Wraps a value in Just.

Examples

iex> Funx.Monad.Maybe.just(2)
%Funx.Monad.Maybe.Just{value: 2}
@spec just?(t(any())) :: boolean()

Returns true if the Maybe is Just, otherwise false.

Examples

iex> Funx.Monad.Maybe.just?(Funx.Monad.Maybe.just(5))
true

iex> Funx.Monad.Maybe.just?(Funx.Monad.Maybe.nothing())
false

Converts an Either to a Maybe. Right becomes Just, and Left becomes Nothing.

Examples

iex> Funx.Monad.Maybe.lift_either(Funx.Monad.Either.right(5))
%Funx.Monad.Maybe.Just{value: 5}

iex> Funx.Monad.Maybe.lift_either(Funx.Monad.Either.left("Error"))
%Funx.Monad.Maybe.Nothing{}

Lifts an equality function to compare Maybe values:

  • Just vs Just: Uses the custom equality function.
  • Nothing vs Nothing: Always true.
  • Just vs Nothing or vice versa: Always false.

Examples

iex> eq = Funx.Monad.Maybe.lift_eq(%{
...>   eq?: fn x, y -> x == y end,
...>   not_eq?: fn x, y -> x != y end
...> })
iex> eq.eq?.(Funx.Monad.Maybe.just(5), Funx.Monad.Maybe.just(5))
true
iex> eq.eq?.(Funx.Monad.Maybe.just(5), Funx.Monad.Maybe.just(10))
false
iex> eq.eq?.(Funx.Monad.Maybe.nothing(), Funx.Monad.Maybe.nothing())
true
iex> eq.eq?.(Funx.Monad.Maybe.just(5), Funx.Monad.Maybe.nothing())
false

Converts an Identity value into a Maybe. If the value is nil, returns Nothing; otherwise Just.

Examples

iex> Funx.Monad.Maybe.lift_identity(Funx.Monad.Identity.pure(5))
%Funx.Monad.Maybe.Just{value: 5}

iex> Funx.Monad.Maybe.lift_identity(Funx.Monad.Identity.pure(nil))
%Funx.Monad.Maybe.Nothing{}

Adapts an ordering function to compare Maybe values:

  • Nothing is considered less than any Just.
  • Two Just values are compared by the provided function.

Examples

iex> ord = Funx.Monad.Maybe.lift_ord(%{
...>   lt?: &</2,
...>   le?: &<=/2,
...>   gt?: &>/2,
...>   ge?: &>=/2
...> })
iex> ord.lt?.(Funx.Monad.Maybe.just(3), Funx.Monad.Maybe.just(5))
true
iex> ord.lt?.(Funx.Monad.Maybe.nothing(), Funx.Monad.Maybe.just(5))
true
Link to this function

lift_predicate(value, predicate)

View Source
@spec lift_predicate(term(), (term() -> boolean())) :: t(term())

Lifts a value into Maybe based on a predicate. If predicate.(value) is true, returns Just(value); otherwise Nothing.

Examples

iex> Funx.Monad.Maybe.lift_predicate(5, fn x -> x > 3 end)
%Funx.Monad.Maybe.Just{value: 5}

iex> Funx.Monad.Maybe.lift_predicate(2, fn x -> x > 3 end)
%Funx.Monad.Maybe.Nothing{}
@spec nothing() :: Funx.Monad.Maybe.Nothing.t()

Returns a Nothing value.

Examples

iex> Funx.Monad.Maybe.nothing()
%Funx.Monad.Maybe.Nothing{}
@spec nothing?(t(any())) :: boolean()

Returns true if the Maybe is Nothing, otherwise false.

Examples

iex> Funx.Monad.Maybe.nothing?(Funx.Monad.Maybe.nothing())
true

iex> Funx.Monad.Maybe.nothing?(Funx.Monad.Maybe.just(5))
false
Link to this function

or_else(just, fallback_fun)

View Source
@spec or_else(t(value), (-> t(value))) :: t(value) when value: var

Returns the current Just value or invokes the fallback_fun if Nothing.

Examples

iex> Funx.Monad.Maybe.or_else(Funx.Monad.Maybe.nothing(), fn -> Funx.Monad.Maybe.just(42) end)
%Funx.Monad.Maybe.Just{value: 42}

iex> Funx.Monad.Maybe.or_else(Funx.Monad.Maybe.just(10), fn -> Funx.Monad.Maybe.just(42) end)
%Funx.Monad.Maybe.Just{value: 10}
@spec pure(any()) :: Funx.Monad.Maybe.Just.t(any())

Alias for just/1.

Examples

iex> Funx.Monad.Maybe.pure(5)
%Funx.Monad.Maybe.Just{value: 5}
@spec sequence([t(value)]) :: t([value]) when value: any()

Converts a list of Maybe values into a Maybe containing a list. If any element is Nothing, the entire result is Nothing.

Examples

iex> Funx.Monad.Maybe.sequence([Funx.Monad.Maybe.just(1), Funx.Monad.Maybe.just(2)])
%Funx.Monad.Maybe.Just{value: [1, 2]}

iex> Funx.Monad.Maybe.sequence([Funx.Monad.Maybe.just(1), Funx.Monad.Maybe.nothing()])
%Funx.Monad.Maybe.Nothing{}
@spec to_nil(t(value)) :: nil | value when value: term()

Converts a Maybe to its wrapped value or nil.

Examples

iex> Funx.Monad.Maybe.to_nil(Funx.Monad.Maybe.just(5))
5

iex> Funx.Monad.Maybe.to_nil(Funx.Monad.Maybe.nothing())
nil
@spec to_predicate(t(any())) :: boolean()

Returns true if the given Maybe is a Just, or false if it is Nothing.

This provides a simple way to treat a Maybe as a boolean condition, useful when filtering or making branching decisions based on presence.

Examples

iex> Funx.Monad.Maybe.to_predicate(Funx.Monad.Maybe.just(42))
true

iex> Funx.Monad.Maybe.to_predicate(Funx.Monad.Maybe.nothing())
false

Raises an error if the input is not a Just or Nothing.

@spec to_result(t(right)) :: {:ok, right} | {:error, :nothing} when right: term()

Converts a Maybe to a result tuple. Just(value) becomes {:ok, value}, while Nothing becomes {:error, :nothing}.

Examples

iex> Funx.Monad.Maybe.to_result(Funx.Monad.Maybe.just(5))
{:ok, 5}

iex> Funx.Monad.Maybe.to_result(Funx.Monad.Maybe.nothing())
{:error, :nothing}
Link to this function

to_try!(maybe, message \\ "Nothing value encountered")

View Source
@spec to_try!(t(right), String.t()) :: right | no_return() when right: term()

Extracts a value from a Maybe, raising an exception if Nothing.

Examples

iex> Funx.Monad.Maybe.to_try!(Funx.Monad.Maybe.just(5))
5

iex> Funx.Monad.Maybe.to_try!(Funx.Monad.Maybe.nothing(), "No value found")
** (RuntimeError) No value found
@spec traverse([input], (input -> t(output))) :: t([output])
when input: any(), output: any()

Applies a function to each element of a list, collecting results into a single Maybe. If any call returns Nothing, the operation halts and returns Nothing.

Examples

iex> Funx.Monad.Maybe.traverse([1, 2], fn x -> Funx.Monad.Maybe.just(x * 2) end)
%Funx.Monad.Maybe.Just{value: [2, 4]}

iex> Funx.Monad.Maybe.traverse([1, nil, 3], fn
...>   nil -> Funx.Monad.Maybe.nothing()
...>   x -> Funx.Monad.Maybe.just(x * 2)
...> end)
%Funx.Monad.Maybe.Nothing{}