mo

repository·master·Indexed 25 days ago

https://github.com/samber/mo

A Go library that brings monads and functional programming (FP) abstractions to Go using Generics. It provides types such as Option, Result, Either, EitherX (3 to 5 types), Future, IO, IOEither, Task, TaskEither, and State to handle optionality, errors, and side effects more declaratively.

Tokens
7.7K
Snippets
2
Records
64
Agent score
85%

What's inside mo

  1. Quick start with Option and Pipe3

    master

    You can use mo.Option[T] to represent optional values. The option sub-package provides functional composition tools like Pipe3 to chain transformations such as Map and FlatMap.

    Supported data types in mo include:

    • Option[T]
    • Result[T]
    • Either[A, B]
    • EitherX[T1, ..., TX] (where X is 3 to 5)
    • Future[T]
    • IO[T]
    • IOEither[T]
    • Task[T]
    • TaskEither[T]
    • State[S, A]
    import (
        "github.com/samber/mo"
        "github.com/samber/mo/option"
    )
    
    out := option.Pipe3(
        mo.Some(21),
        option.Map(func(v int) int { return v * 2 }),
        option.FlatMap(func(v int) mo.Option[int] { return mo.None[int]() }),
        option.Map(func(v int) int { return v + 21 }),
    )
    // out == None[int]
  2. Install mo

    master

    Install the mo library using go get. The library is v1 and follows SemVer strictly. It has no dependencies other than the Go standard library.

    To add the AI Agent Skill for samber/mo, use the following command:

    go get github.com/samber/mo@v1
    
    # AI Agent Skill
    npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-mo
  3. Use Option methods: FlatMap, OrElse, and Match

    master

    The Option[T] type provides several methods for handling values:

    • FlatMap: Chains operations that return another Option.
    • OrElse: Returns the contained value if present, otherwise returns the provided default.
    • Match: Provides a way to handle both the presence and absence of a value via callback functions.
  4. Use Option[T] for optional values

    master

    Option is a container for an optional value of type T. It is either Some (value exists) or None (value is absent).

    Constructors

    • mo.Some()
    • mo.None()
    • mo.TupleToOption()
    • mo.EmptyableToOption()
    • mo.PointerToOption()

    Common Methods

    • .IsPresent(), .IsSome(), .IsAbsent(), .IsNone(): Check the state of the option.
    • .Get(), .MustGet(): Retrieve the value.
    • .OrElse(), .OrEmpty(): Provide fallback values.
    • .Map(), .FlatMap(): Transform the contained value.
    • .Match(): Handle both Some and None cases.
    • .ToPointer(): Convert to a pointer.

    Sub-package option

    Provides functional transformations and pipes:

    • option.Map()()
    • option.FlatMap()()
    • option.Match()()
    • option.FlatMatch()()
    • option.Pipe1..Pipe10()
  5. Use Future[T] for asynchronous values

    master

    Future represents a value that may not be available yet but will be at some point, or an exception if it cannot be produced.

    Constructors

    • mo.NewFuture()

    Common Methods

    • .Then(): Chain operations.
    • .Catch(): Handle errors/exceptions.
    • .Finally(): Execute logic regardless of outcome.
    • .Collect(): Gather results.
    • .Result(): Convert to a Result type.
    • .Cancel(): Cancel the future.
  6. Use Foldable for reducing containers

    master

    Foldable represents a type that can be folded into a single value based on its state.

    Folding Function

    • mo.Fold[T, U, R any](f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) R
  7. Use State[S, A] for stateful computations

    master

    State represents a function (S) -> (A, S), where S is the state and A is the result.

    Constructors

    • mo.NewState()
    • mo.ReturnState()

    Common Methods

    • .Run(): Execute the state function.
    • .Get(): Retrieve the current state.
    • .Modify(): Update the state.
    • .Put(): Replace the state.
  8. Use IO and IOEither for synchronous side effects

    master

    IO[T]

    Represents a non-deterministic synchronous computation that can cause side effects, yields a value of type T, and never fails.

    • Constructors: mo.NewIO(), mo.NewIO1(), ..., mo.NewIO5()
    • Method: .Run()

    IOEither[T]

    Represents a non-deterministic synchronous computation that can cause side effects, yields a value of type T, and can fail.

    • Constructors: mo.NewIOEither(), mo.NewIOEither1(), ..., mo.NewIOEither5()
    • Method: .Run()
  9. Use Result[T] for success or failure outcomes

    master

    Result represents the outcome of an action that is either a success (Ok) or a failure (Err). It is functionally similar to Either[error, T].

    Constructors

    • mo.Ok()
    • mo.Err()
    • mo.Errf()
    • mo.TupleToResult()
    • mo.Try()

    Common Methods

    • .IsOk(), .IsError(): Check the status.
    • .Error(): Retrieve the error.
    • .Get(), .MustGet(): Retrieve the success value.
    • .OrElse(), .OrEmpty(): Provide fallbacks.
    • .ToEither(): Convert to an Either type.
    • .Map(), .MapErr(), .FlatMap(): Transform success or error values.
    • .Match(): Handle both Ok and Err cases.

    Sub-package result

    Provides functional transformations and pipes:

    • result.Map()()
    • result.FlatMap()()
    • result.Match()()
    • result.FlatMatch()()
    • result.Pipe1..Pipe10()

    Helper

    • mo.Do[T any](fn func() T) (result mo.Result[T]): Wraps a function execution into a Result.
  10. Use Either[L, R] for two possible types

    master

    Either represents a value that can be one of two types: Left or Right.

    Constructors

    • mo.Left()
    • mo.Right()

    Common Methods

    • .IsLeft(), .IsRight(): Check the type.
    • .Left(), .Right(): Retrieve the value.
    • .MustLeft(), .MustRight(): Retrieve the value or panic.
    • .Unpack(): Extract both values.
    • .LeftOrElse(), .RightOrElse(), .LeftOrEmpty(), .RightOrEmpty(): Handle fallback logic.
    • .Swap(): Switch Left and Right.
    • .Match(): Handle both cases.
    • .MapLeft(), .MapRight(): Transform one side of the Either.

    Sub-package either

    Provides functional transformations and pipes:

    • either.MapLeft()()
    • either.MapRight()()
    • either.Match()()
    • either.Swap()()
    • either.Pipe1..Pipe10()
  11. Use Task and TaskEither for asynchronous side effects

    master

    Task[T]

    Represents a non-deterministic asynchronous computation that can cause side effects, yields a value of type T, and never fails.

    • Constructors: mo.NewTask(), mo.NewTask1(), ..., mo.NewTask5(), mo.NewTaskFromIO(), ..., mo.NewTaskFromIO5()
    • Method: .Run()

    TaskEither[T]

    Represents a non-deterministic asynchronous computation that can cause side effects, yields a value of type T, and can fail.

    • Constructors: mo.NewTaskEither(), mo.NewTaskEitherFromIOEither()
    • Methods: .Run(), .OrElse(), .Match(), .TryCatch(), .ToTask(), .ToEither()
  12. Use EitherX for multiple possible types (3 to 5)

    master

    EitherX represents a value of X possible types (where X is between 3 and 5). For example, Either3 can be T1, T2, or T3.

    Constructors

    Constructors are named based on which argument is provided:

    • mo.NewEither3Arg1[A, B, C](A)
    • mo.NewEither3Arg2[A, B, C](B)
    • mo.NewEither3Arg3[A, B, C](C)
    • (Similar patterns exist for Either4 and Either5)

    Common Methods

    • .IsArgX(): Check if the value is of type ArgX.
    • .ArgX(): Retrieve the value of type ArgX.
    • .MustArgX(): Retrieve the value or panic.
    • .Unpack(): Extract all possible values.
    • .ArgXOrElse(), .ArgXOrEmpty(): Handle fallbacks.
    • .Match(): Handle all possible cases.
    • .MapArgX(): Transform a specific argument type.