monad-maybe

Installation
SKILL.md

Maybe Monad

Installation: If not already installed, add the package with pnpm add @efesto-cloud/maybe.

Use this skill to keep Maybe<T> usage simple and predictable.

Core Rules

  • Wrap optional value with Maybe.maybe(value).
  • Build explicit presence with Maybe.some(value).
  • Build explicit absence with Maybe.none().
  • Check state with isSome() / isNone().
  • Provide fallback with else(() => defaultValue).
  • Convert to Result when needed with toResult() — returns Result<T, NoneError>.
  • Pattern match with fold(onNone, onSome) when both branches need to return the same type.
  • Execute side effects with run(fn => {...}) — Some runs the function, None does nothing.
  • Serialize to plain object with toObject() — returns ISome<T> | INone.
  • Deserialize with Maybe.fromObject(obj) — reconstructs from { some: boolean, data: T | null }.
  • Combine two Maybes with Maybe.combine(m1, m2) — returns Maybe<[T1, T2]>.

Common Mistakes To Avoid

  • Do not treat Maybe like Result.
  • Do not use isFailure on Maybe.
  • Do not access .data without checking isSome() first.

Procedure

  1. Identify nullable or optional source values.
  2. Convert early to Maybe (Maybe.maybe(value)).
  3. Use one handling style consistently:
    • Branching: if (m.isNone()) ... else m.data
    • Functional: map, flatMap, filter, fold
    • Fallback: m.else(() => defaultValue)
  4. If caller expects Result<T, E>, convert once with toResult() and continue in Result flow.

Quick Patterns

const maybeEmail = Maybe.maybe(input.email);
if (maybeEmail.isNone()) return Result.err(new Error("Missing email"));

return Result.ok(maybeEmail.data.trim());
const displayName = Maybe.maybe(user.nickname)
	.filter((v) => v.length > 0)
	.else(() => user.nome)
	.data;
Related skills
Installs
2
First Seen
9 days ago