### Install mo Library Source: https://github.com/samber/mo/blob/master/README.md Install the mo library using go get. Includes an AI Agent Skill command for Golang integration. ```sh go get github.com/samber/mo@v1 # AI Agent Skill npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-mo ``` -------------------------------- ### Install samber/mo Library Source: https://github.com/samber/mo/blob/master/_autodocs/00-index.md Install the latest version of the samber/mo library using the go get command. This library has no external dependencies and relies solely on the Go standard library. ```bash go get github.com/samber/mo@v1 ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/samber/mo/blob/master/README.md Installs necessary development dependencies for the project. Run this command before other development tasks. ```bash make tools ``` -------------------------------- ### Task and Task1 Examples Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Examples demonstrating the creation of Task and Task1 with their respective function signatures. Task represents a computation that returns a Future. ```go task := mo.NewTask(func() *mo.Future[int] { return mo.NewFuture[int](func(resolve func(int), reject func(error)) { resolve(42) }) }) task1 := mo.NewTask1(func(x int) *mo.Future[int] { return mo.NewFuture[int](func(resolve func(int), reject func(error)) { resolve(x * 2) }) }) ``` -------------------------------- ### Create and Run IOEither Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Demonstrates how to create IOEither instances with and without parameters, and how to execute them to get an Either result. ```go // Constructors io := mo.NewIOEither[int](func() (int, error) { return 42, nil }) io1 := mo.NewIOEither1[int, string](func(s string) (int, error) { return len(s), nil }) // ... NewIOEither2, ... NewIOEither5 // Execution either := io.Run() // Either[error, T] either := io1.Run("hello") // Right(5) ``` -------------------------------- ### Chaining Option Transformations with Pipe3 Source: https://github.com/samber/mo/blob/master/_autodocs/06-transformations-and-pipes.md Example demonstrating how to chain multiple transformations (Map, FlatMap, Map) on an Option using Pipe3. The final result is None because an intermediate FlatMap returns None. ```go import "github.com/samber/mo/option" result := 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 }), ) // result = None ``` -------------------------------- ### Task[T] Constructor and Execution Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Define asynchronous tasks with NewTask and execute them to get a Future. Similar constructors exist for tasks with parameters. ```go // Constructor task := mo.NewTask[int](func() *mo.Future[int] { return mo.NewFuture[int](func(resolve func(int), reject func(error)) { resolve(42) }) }) // Execution future := task.Run() // returns *Future[T] future2 := future.Then(...) // chain as with Future ``` -------------------------------- ### Create Option with None Value Source: https://github.com/samber/mo/blob/master/_autodocs/01-option.md Use `mo.None` to construct an Option representing the absence of a value. Attempting to `Get` a None Option will return the zero value and `false`. ```go package main import "github.com/samber/mo" func main() { opt := mo.None[int]() _, ok := opt.Get() // ok = false } ``` -------------------------------- ### Compose State Monad Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Demonstrates running a State monad computation. The get State monad returns the current state as its value and leaves the state unchanged. ```go get := mo.NewState[int, int](func(s int) (int, int) { return s, s }) result, finalState := get.Run(10) ``` -------------------------------- ### Example of Mapping an Either3 Argument Source: https://github.com/samber/mo/blob/master/_autodocs/06-transformations-and-pipes.md Demonstrates how to use MapArg2 to transform the second argument of an Either3. The provided function modifies the integer value, returning a new Either3 with the transformed value. ```go import "github.com/samber/mo/either3" either := mo.NewEither3Arg2[string, int, bool](42) result := either3.MapArg2(func(v int) (string, int, bool) { return "", v * 2, false })(either) // result = NewEither3Arg2(84) ``` -------------------------------- ### Create Option with Some Value Source: https://github.com/samber/mo/blob/master/_autodocs/01-option.md Use `mo.Some` to construct an Option containing a present value. The value can be retrieved using the `Get` method. ```go package main import "github.com/samber/mo" func main() { opt := mo.Some(42) val, ok := opt.Get() // val = 42, ok = true } ``` -------------------------------- ### Either3 Value or Fallback Source: https://github.com/samber/mo/blob/master/_autodocs/05-either3-4-5.md Use ArgXOrElse to get the contained value or a specified fallback if the argument is not present. ```go e := mo.NewEither3Arg2[string, int, bool](42) e.Arg1OrElse("default") // "default" e.Arg2OrElse(0) // 42 e.Arg3OrElse(false) // false ``` -------------------------------- ### Modify and Update State Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Demonstrates operations on State computations, including getting the current state, modifying it based on a function, and putting a new state. ```go // Operations getState := state.Get() // State[S, S] modified := state.Modify(func(s int) int { return s * 2 }) updated := state.Put(10) // set new state ``` -------------------------------- ### Chain Option Operations with FlatMap and OrElse Source: https://github.com/samber/mo/blob/master/README.md Chains multiple FlatMap operations on an Option, followed by OrElse to provide a default value if the Option is None. This example shows how to transform and extract a value from an Option. ```go option1 := mo.Some(42) // Some(42) option1. FlatMap(func (value int) Option[int] { return Some(value*2) }). FlatMap(func (value int) Option[int] { return Some(value%2) }). FlatMap(func (value int) Option[int] { return Some(value+21) }). OrElse(1234) // 21 option2 := mo.None[int]() // None option2.OrElse(1234) // 1234 ``` -------------------------------- ### Create and Execute State Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Illustrates the creation of State computations using constructors like NewState and ReturnState, and their execution with Run. ```go // Constructors state := mo.NewState[int, string](func(s int) (string, int) { return fmt.Sprintf("state is %d", s), s + 1 }) state := mo.ReturnState[int, string]("constant") // Execution val, newState := state.Run(5) // ("state is 5", 6) ``` -------------------------------- ### Get Value or Fallback - Go Source: https://github.com/samber/mo/blob/master/_autodocs/02-result.md Use `OrElse` to get the contained value if the Result is successful, or a provided fallback value if it's an error. ```go func (r Result[T]) OrElse(fallback T) T ``` ```go mo.Ok(42).OrElse(0) // 42 mo.Err[int](err).OrElse(0) // 0 ``` -------------------------------- ### Get Option Value Safely Source: https://github.com/samber/mo/blob/master/_autodocs/01-option.md The Get method retrieves the value from an Option and a boolean indicating its presence. It returns the zero value for the type and false if the Option is absent. ```go func (o Option[T]) Get() (T, bool) ``` ```go opt := mo.Some(42) val, ok := opt.Get() // val = 42, ok = true opt2 := mo.None[int]() val2, ok2 := opt2.Get() // val2 = 0, ok2 = false ``` -------------------------------- ### Get Value and Error from Result - Go Source: https://github.com/samber/mo/blob/master/_autodocs/02-result.md Use `Get` to retrieve both the value and the error from a Result. It returns the value and nil on success, or the zero value of the type and the error on failure. ```go func (r Result[T]) Get() (T, error) ``` ```go val, err := mo.Ok(42).Get() // val = 42, err = nil val2, err2 := mo.Err[int](errors.New("failed")).Get() // val2 = 0, err2 = error ``` -------------------------------- ### IO[T] Constructors and Execution Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Create synchronous IO actions with NewIO and NewIO1 (up to NewIO5). Execute them synchronously using Run. ```go // Constructors io := mo.NewIO[int](func() int { return 42 }) io1 := mo.NewIO1[int, string](func(s string) int { return len(s) }) // ... NewIO2, ... NewIO5 // Execution val := io.Run() // execute synchronously val := io1.Run("hello") // 5 ``` -------------------------------- ### Zero-Initialization of mo.Option Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Demonstrates the correct way to initialize an `mo.Option` type for zero-initialization safety when using Go 1.18+ generics. ```go var opt mo.Option[int] = None[int]() ``` -------------------------------- ### Get Option Value or Zero Value Source: https://github.com/samber/mo/blob/master/_autodocs/01-option.md OrEmpty returns the contained value if the Option is present, otherwise it returns the zero value for the Option's type. This is a convenient way to get a usable value. ```go func (o Option[T]) OrEmpty() T ``` ```go mo.Some(42).OrEmpty() // 42 mo.None[int]().OrEmpty() // 0 ``` -------------------------------- ### Get Source: https://github.com/samber/mo/blob/master/_autodocs/02-result.md Retrieves both the value and the error from the Result. ```APIDOC ## Get ### Description Returns the value and error. ### Method `Get()` ### Returns - `(value, nil)` if successful - `(zero value, error)` if failed ### Example ```go val, err := mo.Ok(42).Get() // val = 42, err = nil val2, err2 := mo.Err[int](errors.New("failed")).Get() // val2 = 0, err2 = error ``` ``` -------------------------------- ### Create and Use TaskEither Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Shows how to construct a TaskEither, and use methods like OrElse, ToEither, Match, and ToTask for handling asynchronous operations that can fail. ```go // Constructor taskEither := mo.NewTaskEither[int](func() *mo.Future[int] { return mo.NewFuture[int](func(resolve func(int), reject func(error)) { // ... }) }) // Methods val := taskEither.OrElse(0) // waits for result, returns value or default either := taskEither.ToEither() result := taskEither.Match(onLeft, onRight) task := taskEither.ToTask(fallback) ``` -------------------------------- ### Get Source: https://github.com/samber/mo/blob/master/_autodocs/01-option.md Retrieves the value and a boolean indicating its presence. Returns the zero value of T if absent. ```APIDOC ## Get ### Description Returns the value and a boolean indicating presence. ### Method ```go func (o Option[T]) Get() (T, bool) ``` ### Returns - `(value, true)` if present - `(empty value, false)` if absent ### Example ```go opt := mo.Some(42) val, ok := opt.Get() // val = 42, ok = true opt2 := mo.None[int]() val2, ok2 := opt2.Get() // val2 = 0, ok2 = false ``` ``` -------------------------------- ### Using Do to Wrap Panicking Functions Source: https://github.com/samber/mo/blob/master/_autodocs/02-result.md Demonstrates how to use the Do function to wrap a function that might panic, converting panics into Err results. ```go package main import "github.com/samber/mo" func parseInt(s string) mo.Result[int] { return mo.Do(func() int { i, err := strconv.Atoi(s) if err != nil { panic(err) } return i }) } ``` -------------------------------- ### Importing mo Library Packages Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Import the necessary packages from the mo library for Option, Result, Either, and other utilities. ```go import ( "github.com/samber/mo" "github.com/samber/mo/option" "github.com/samber/mo/result" "github.com/samber/mo/either" ) ``` -------------------------------- ### State Get Method Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Returns the current state as the result of a State computation without modifying the state. ```go func (s State[S, A]) Get() State[S, S] ``` -------------------------------- ### Serialization with JSON and Binary Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Shows how to serialize and deserialize Mo types using standard JSON and binary formats. Includes support for sql.Scanner and driver.Valuer interfaces. ```go // All types support: data, err := json.Marshal(opt) err := json.Unmarshal(data, &opt) // Option, Result support: data, err := opt.MarshalBinary() err := (&opt).UnmarshalBinary(data) // Option, Result work with: err := opt.Scan(dbValue) // sql.Scanner val, err := opt.Value() // driver.Valuer ``` -------------------------------- ### Import Entire mo Library into Namespace Source: https://github.com/samber/mo/blob/master/README.md Imports the entire 'mo' library into the current namespace using a blank identifier for brevity. Use with caution as it can lead to naming conflicts. ```go import ( . "github.com/samber/mo" ) ``` -------------------------------- ### Result[T] Accessors Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Access values from Result types using Get, MustGet, OrElse, IsOk, IsError, and Error. ```go // Accessors val, err := res.Get() // (T, error) val := res.MustGet() // T or panic val := res.OrElse(42) // T is := res.IsOk() // bool is := res.IsError() // bool err := res.Error() // error ``` -------------------------------- ### Compose Option Transformations with Pipe3 Source: https://github.com/samber/mo/blob/master/README.md Demonstrates composing transformations on an Option type using the Pipe3 helper from the option sub-package. Note that FlatMap can result in None. ```go 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] ``` -------------------------------- ### Import mo Library in Go Source: https://github.com/samber/mo/blob/master/README.md Import the mo library into your Go project using the provided import path. ```go import ( "github.com/samber/mo" ) ``` -------------------------------- ### Pipe Composition for Functional Chaining Source: https://github.com/samber/mo/blob/master/_autodocs/00-index.md Demonstrates functional-style pipe composition using `option.Pipe3`. This pattern allows for a readable sequence of transformations on a value, especially with `mo.Option`. ```Go import "github.com/samber/mo/option" result := 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 }), ) ``` -------------------------------- ### Get Value or Panic - Go Source: https://github.com/samber/mo/blob/master/_autodocs/02-result.md The `MustGet` method returns the wrapped value. It will panic with the contained error if the Result is in an error state. ```go func (r Result[T]) MustGet() T ``` ```go val := mo.Ok(42).MustGet() // val = 42 mo.Err[int](errors.New("failed")).MustGet() // panics with error ``` -------------------------------- ### Run Tests Source: https://github.com/samber/mo/blob/master/README.md Executes the project's test suite. Use 'make watch-test' for continuous testing during development. ```bash make test ``` ```bash make watch-test ``` -------------------------------- ### Convert IO to Task Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Converts an IO action to a Task and then runs it to get a Future. Useful for integrating IO operations into a Task-based workflow. ```go // IO to Task io := mo.NewIO(func() int { return 42 }) task := mo.NewTaskFromIO(io) future := task.Run() ``` -------------------------------- ### Get Option Value or Panic Source: https://github.com/samber/mo/blob/master/_autodocs/01-option.md MustGet returns the value contained within the Option. It will panic if the Option is absent, so use this only when presence is guaranteed. ```go func (o Option[T]) MustGet() T ``` ```go opt := mo.Some(42) val := opt.MustGet() // val = 42 opt2 := mo.None[int]() opt2.MustGet() // panics ``` -------------------------------- ### Global Utilities: Fold, Do, and Type Conversions Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Illustrates global utility functions like Fold for foldable types, Do for converting panics to errors, and various type conversion helpers. These utilities simplify common programming tasks. ```go // Fold — generic operation on Foldable types result := mo.Fold( someOption, func(val int) string { return "success" }, func(err error) string { return "failure" }, ) // Do — convert panics to errors result := mo.Do(func() int { panic("error") }) // result = Err[int](error("error")) // Type conversions opt := mo.TupleToOption(val, ok) res := mo.TupleToResult(val, err) res := mo.Try(func() (T, error) { ... }) ptr := opt.ToPointer() either := res.ToEither() ``` -------------------------------- ### Optional Value Handling with Chaining Source: https://github.com/samber/mo/blob/master/_autodocs/00-index.md Illustrates chaining operations on optional values using `mo.Option`. This is useful for safely handling values that might be absent, preventing nil pointer exceptions. ```Go opt := mo.Some(42) opt. Map(func(v int) (int, bool) { return v * 2, true }). FlatMap(func(v int) mo.Option[int] { if v > 100 { return mo.Some(v) } return mo.None[int]() }). ForEach(func(v int) { println(v) }) ``` -------------------------------- ### Get Value or Zero Value - Go Source: https://github.com/samber/mo/blob/master/_autodocs/02-result.md The `OrEmpty` method returns the contained value if successful, or the zero value for the type if the Result is an error. ```go func (r Result[T]) OrEmpty() T ``` ```go mo.Ok(42).OrEmpty() // 42 mo.Err[int](err).OrEmpty() // 0 (for int) ``` -------------------------------- ### Get Option Size Source: https://github.com/samber/mo/blob/master/_autodocs/01-option.md The Size method returns 1 if the Option contains a value, and 0 if it is absent. This provides a quick way to check for presence. ```go func (o Option[T]) Size() int ``` ```go mo.Some(42).Size() // 1 mo.None[int]().Size() // 0 ``` -------------------------------- ### Functional Pipeline with Option Source: https://github.com/samber/mo/blob/master/_autodocs/06-transformations-and-pipes.md Demonstrates a functional pipeline using option.Pipe5 for a chain of transformations on an Option type. This pattern avoids intermediate variables and promotes declarative code. ```go import ( "github.com/samber/mo" "github.com/samber/mo/option" ) func main() { pipeline := option.Pipe5( mo.Some(5), option.Map(func(x int) int { return x * 2 }), option.Map(func(x int) int { return x + 3 }), option.FlatMap(func(x int) mo.Option[int] { if x > 10 { return mo.Some(x) } return mo.None[int]() }), option.Map(func(x int) int { return x / 2 }), option.Map(func(x int) int { return x - 1 }), ) // Result processing val, ok := pipeline.Get() if ok { println(val) // 6 } } ``` -------------------------------- ### Create IOEither Computations Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Use NewIOEither constructors for synchronous computations that can fail. The constructor function must return a value and an error. ```go func NewIOEither[R any](f fe0[R]) IOEither[R] func NewIOEither1[R any, A any](f fe1[R, A]) IOEither1[R, A] func NewIOEither2[R any, A any, B any](f fe2[R, A, B]) IOEither2[R, A, B] func NewIOEither3[R any, A any, B any, C any](f fe3[R, A, B, C]) IOEither3[R, A, B, C] func NewIOEither4[R any, A any, B any, C any, D any](f fe4[R, A, B, C, D]) IOEither4[R, A, B, C, D] func NewIOEither5[R any, A any, B any, C any, D any, E any](f fe5[R, A, B, C, D, E]) IOEither5[R, A, B, C, D, E] ``` ```go io := mo.NewIOEither(func() (int, error) { return 42, nil }) io1 := mo.NewIOEither1(func(x int) (int, error) { if x < 0 { return 0, errors.New("negative number") } return x * 2, nil }) ``` -------------------------------- ### Checking and Retrieving Either3 Values Source: https://github.com/samber/mo/blob/master/_autodocs/05-either3-4-5.md Use IsArgX to check for presence and ArgX to retrieve values. MustArgX retrieves the value or panics if absent. ```go e := mo.NewEither3Arg2[string, int, bool](42) if e.IsArg2() { val, _ := e.Arg2() println(val) // 42 } val := e.MustArg2() // 42 ``` -------------------------------- ### Option[T] Accessors Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Access values from Option types using methods like Get, MustGet, OrElse, OrEmpty, PointerToOption, IsPresent, IsSome, IsAbsent, and IsNone. ```go // Accessors val, ok := opt.Get() // (T, bool) val := opt.MustGet() // T or panic val := opt.OrElse(42) // T val := opt.OrEmpty() // T ptr := opt.ToPointer() // *T or nil is := opt.IsPresent() // bool is := opt.IsSome() // bool is := opt.IsAbsent() // bool is := opt.IsNone() // bool ``` -------------------------------- ### Either5 Constructors Source: https://github.com/samber/mo/blob/master/_autodocs/05-either3-4-5.md Use these functions to create new Either5 instances, specifying which of the five possible arguments the value corresponds to. ```go func NewEither5Arg1[T1 any, T2 any, T3 any, T4 any, T5 any](value T1) Either5[T1, T2, T3, T4, T5] func NewEither5Arg2[T1 any, T2 any, T3 any, T4 any, T5 any](value T2) Either5[T1, T2, T3, T4, T5] func NewEither5Arg3[T1 any, T2 any, T3 any, T4 any, T5 any](value T3) Either5[T1, T2, T3, T4, T5] func NewEither5Arg4[T1 any, T2 any, T3 any, T4 any, T5 any](value T4) Either5[T1, T2, T3, T4, T5] func NewEither5Arg5[T1 any, T2 any, T3 any, T4 any, T5 any](value T5) Either5[T1, T2, T3, T4, T5] ``` -------------------------------- ### TaskEither OrElse Example Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Handle potential failures in a TaskEither computation. The OrElse method returns the computed value if successful, or a specified fallback value if an error occurs. ```go task := mo.NewTaskEither[int](func() *mo.Future[int] { return mo.NewFuture[int](func(resolve func(int), reject func(error)) { reject(errors.New("failed")) }) }) result := task.OrElse(0) // result = 0 (after computation completes) ``` -------------------------------- ### Chaining Operators with PipeN Source: https://github.com/samber/mo/blob/master/_autodocs/06-transformations-and-pipes.md Illustrates the general structure of pipe functions, showing how to chain multiple operators onto a source value. This pattern is equivalent to nested function calls. ```go result := PipeN( source, operator1, operator2, operator3, ) // Equivalent to: result = operator3(operator2(operator1(source))) ``` -------------------------------- ### Chaining Operations with Pipe3 Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Shows how to chain multiple operations (Map, FlatMap) on an Option type using Pipe3. Ensure the source value is correctly provided. ```go import "github.com/samber/mo/option" // Pipe1 through Pipe10 available for each type result := option.Pipe3( source, option.Map(func(v int) int { return v * 2 }), option.FlatMap(func(v int) mo.Option[int] { return mo.Some(v) }), option.Map(func(v int) int { return v + 1 }), ) ``` -------------------------------- ### Get Option Value or Fallback Source: https://github.com/samber/mo/blob/master/_autodocs/01-option.md OrElse returns the contained value if the Option is present, otherwise it returns the provided fallback value. This is useful for providing default values. ```go func (o Option[T]) OrElse(fallback T) T ``` ```go mo.Some(42).OrElse(0) // 42 mo.None[int]().OrElse(0) // 0 ``` -------------------------------- ### State Constructors Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Use NewState to create a stateful computation and ReturnState to create one that returns a constant value without changing state. ```go func NewState[S any, A any](f func(state S) (A, S)) State[S, A] func ReturnState[S any, A any](x A) State[S, A] ``` ```go // Create a state that increments a counter inci := mo.NewState[int, int](func(state int) (int, int) { return state, state + 1 }) // Return a constant value without changing state const10 := mo.ReturnState[int, int](10) ``` -------------------------------- ### Option[T] Constructors Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Create Option types using constructors like Some, None, TupleToOption, PointerToOption, and EmptyableToOption. ```go // Constructors some := mo.Some(42) none := mo.None[int]() opt := mo.TupleToOption(val, ok) opt := mo.PointerToOption(ptr) opt := mo.EmptyableToOption(val) ``` -------------------------------- ### Get Left Value or Fallback Source: https://github.com/samber/mo/blob/master/_autodocs/03-either.md Use `LeftOrElse` to retrieve the left value if present, otherwise return a specified fallback value. This is useful for providing default values when an error occurs. ```go mo.Left[string, int]("error").LeftOrElse("default") // "error" mo.Right[string, int](42).LeftOrElse("default") // "default" ``` -------------------------------- ### Error Handling: Multiple Error Types with Either3 Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Shows how to handle scenarios with multiple distinct error types using Either3, allowing for specific matching and handling of each potential error. ```go // Multiple error types with Either3 result := mo.NewEither3Arg2[ValidationErr, NetworkErr, Data]( NetworkErr{Code: 500}, ) result.Match(validation, network, success) ``` -------------------------------- ### Option Transformations Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Demonstrates common transformation functions for the Option type, including Map, FlatMap, Match, and FlatMatch. Similar functions are available for Result, Either, and other foldable types. ```go import "github.com/samber/mo/option" // For Option f := option.Map(func(v int) int { return v * 2 }) f := option.FlatMap(func(v int) mo.Option[int] { return mo.Some(v*2) }) f := option.Match(onValue, onNone) f := option.FlatMatch(onValue, onNone) ``` -------------------------------- ### State Constructors, Execution, and Operations Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md State represents a stateful computation. It allows for creating stateful operations, running them with an initial state, and performing operations like getting, modifying, or putting the state. ```APIDOC ## State[S, A] ### Description State represents a stateful computation. It allows for creating stateful operations, running them with an initial state, and performing operations like getting, modifying, or putting the state. ### Constructors - `mo.NewState[S, A](func(S) (A, S))`: Creates a new State computation. - `mo.ReturnState[S, A](value A) State[S, A]`: Creates a State that returns a constant value without changing the state. ### Execution - `state.Run(initialState S) (A, S)`: Executes the State computation with an initial state and returns the result and the new state. ### Operations - `state.Get() State[S, S]`: Returns a State that retrieves the current state. - `state.Modify(func(S) S) State[S, void]`: Returns a State that modifies the current state. - `state.Put(newState S) State[S, void]`: Returns a State that sets the state to a new value. ``` -------------------------------- ### Get Left Value or Zero Value Source: https://github.com/samber/mo/blob/master/_autodocs/03-either.md Use `LeftOrEmpty` to retrieve the left value if present, otherwise return the zero value for the left type. This is a convenient shorthand for `LeftOrElse` with a zero value. ```go mo.Left[string, int]("error").LeftOrEmpty() // "error" mo.Right[string, int](42).LeftOrEmpty() // "" (zero value for string) ``` -------------------------------- ### Error Handling: Try and MapErr Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Demonstrates the Try function for executing fallible operations and MapErr for transforming errors. These are fundamental for robust error management. ```go // Try function res := mo.Try(func() (int, error) { return strconv.Atoi("42") }) // MapErr for error transformation res2 := res.MapErr(func(err error) (int, error) { return 0, fmt.Errorf("wrapped: %w", err) }) ``` -------------------------------- ### Get Right Value or Fallback Source: https://github.com/samber/mo/blob/master/_autodocs/03-either.md Use `RightOrElse` to retrieve the right value if present, otherwise return a specified fallback value. This is useful for providing default values when an operation yields no result. ```go mo.Right[string, int](42).RightOrElse(0) // 42 mo.Left[string, int]("error").RightOrElse(0) // 0 ``` -------------------------------- ### Some Constructor Source: https://github.com/samber/mo/blob/master/_autodocs/01-option.md Constructs an Option[T] with a present value. Use this when you have a value that is guaranteed to exist. ```APIDOC ## Some Constructor ### Description Constructs an Option[T] with a present value. ### Signature ```go func Some[T any](value T) Option[T] ``` ### Parameters #### Path Parameters - **value** (T) - Required - The value to wrap in Some ### Returns - **Option[T]** - An Option containing the provided value ### Example ```go package main import "github.com/samber/mo" func main() { opt := mo.Some(42) val, ok := opt.Get() // val = 42, ok = true } ``` ``` -------------------------------- ### Process Payment with Either3 Source: https://github.com/samber/mo/blob/master/_autodocs/05-either3-4-5.md Demonstrates how to use Either3 to handle multiple potential outcomes of a payment processing function, including validation errors, gateway issues, and successful processing. The Match function is used to handle each possible result. ```go func processPayment(amount float64) mo.Either3[string, PaymentError, Receipt] { if amount <= 0 { return mo.NewEither3Arg1[string, PaymentError, Receipt]( "amount must be positive", ) } if gateway.IsDown() { return mo.NewEither3Arg2[string, PaymentError, Receipt]( PaymentError{Code: 503}, ) } receipt := gateway.Process(amount) return mo.NewEither3Arg3[string, PaymentError, Receipt](receipt) } result := processPayment(100) result.Match( func(msg string) mo.Either3[string, PaymentError, Receipt] { log.Println("Validation error:", msg) return result }, func(err PaymentError) mo.Either3[string, PaymentError, Receipt] { log.Println("Payment error:", err.Code) return result }, func(receipt Receipt) mo.Either3[string, PaymentError, Receipt] { log.Println("Payment successful:", receipt.ID) return result }, ) ``` -------------------------------- ### Async Computation Chains with Futures Source: https://github.com/samber/mo/blob/master/_autodocs/00-index.md Shows how to manage asynchronous operations using `mo.Future`. This pattern is ideal for chaining multiple asynchronous tasks and handling their results or errors. ```Go future := mo.NewFuture[int](func(resolve func(int), reject func(error)) { go fetchValue(resolve, reject) }) result := future. Then(func(v int) (int, error) { return v * 2, nil }). Then(func(v int) (int, error) { return v + 10, nil }). Catch(func(err error) (int, error) { return 0, nil }) val, err := result.Collect() ``` -------------------------------- ### Get Future result as a Result type Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Wraps the outcome of a Future's Collect() operation into a Result[T] type, which can be either Ok[T] or Err[error]. This provides a more idiomatic way to handle potential failures. ```go res := future.Result() val, err := res.Get() ``` -------------------------------- ### Either4 Constructors Source: https://github.com/samber/mo/blob/master/_autodocs/05-either3-4-5.md Use these functions to create new Either4 instances, specifying which of the four possible arguments the value corresponds to. ```go func NewEither4Arg1[T1 any, T2 any, T3 any, T4 any](value T1) Either4[T1, T2, T3, T4] func NewEither4Arg2[T1 any, T2 any, T3 any, T4 any](value T2) Either4[T1, T2, T3, T4] func NewEither4Arg3[T1 any, T2 any, T3 any, T4 any](value T3) Either4[T1, T2, T3, T4] func NewEither4Arg4[T1 any, T2 any, T3 any, T4 any](value T4) Either4[T1, T2, T3, T4] ``` -------------------------------- ### Get Future result as an Either type Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Wraps the outcome of a Future's Collect() operation into an Either[error, T] type. This represents the result as either Left(error) or Right(value), facilitating pattern matching. ```go future.Either() ``` -------------------------------- ### Monadic Composition with FlatMap Source: https://github.com/samber/mo/blob/master/_autodocs/07-types-and-utilities.md Demonstrates monadic composition using FlatMap to chain operations on an Option type, preserving type information. ```go value := mo.Some(21). FlatMap(func(v int) mo.Option[int] { return mo.Some(v * 2) }). FlatMap(func(v int) mo.Option[int] { return mo.Some(v + 10) }) ``` -------------------------------- ### Create IO Computations Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Use NewIO constructors to create synchronous, pure, non-deterministic computations that never fail. These functions take a function literal that returns the computation's result. ```go func NewIO[R any](f f0[R]) IO[R] func NewIO1[R any, A any](f f1[R, A]) IO1[R, A] func NewIO2[R any, A any, B any](f f2[R, A, B]) IO2[R, A, B] func NewIO3[R any, A any, B any, C any](f f3[R, A, B, C]) IO3[R, A, B, C] func NewIO4[R any, A any, B any, C any, D any](f f4[R, A, B, C, D]) IO4[R, A, B, C, D] func NewIO5[R any, A any, B any, C any, D any, E any](f f5[R, A, B, C, D, E]) IO5[R, A, B, C, D, E] ``` ```go io := mo.NewIO(func() int { return 42 }) io1 := mo.NewIO1(func(x int) int { return x * 2 }) ``` -------------------------------- ### Multi-Outcome Logic with Either3 Source: https://github.com/samber/mo/blob/master/_autodocs/00-index.md Illustrates handling functions with up to three distinct outcomes (success, error, or specific state) using `mo.Either3`. Use this for complex conditional logic where different paths yield different types of results. ```Go func validateAndProcess(val int) mo.Either3[string, error, int] { if val < 0 { return mo.NewEither3Arg1[string, error, int]("negative value") } if val > 1000 { return mo.NewEither3Arg2[string, error, int](errors.New("overflow")) } return mo.NewEither3Arg3[string, error, int](val * 2) } result := validateAndProcess(50) result.Match( func(msg string) mo.Either3[string, error, int] { log.Println("Validation error:", msg) return result }, func(err error) mo.Either3[string, error, int] { log.Println("Processing error:", err) return result }, func(val int) mo.Either3[string, error, int] { log.Println("Success:", val) return result }, ) ``` -------------------------------- ### Match Option Value Source: https://github.com/samber/mo/blob/master/_autodocs/06-transformations-and-pipes.md Applies one function if the Option has a value, and another function if it is None. Requires importing the 'option' package. ```go opt := mo.Some(42) result := option.Match( func(v int) (int, bool) { return v * 2, true }, func() (int, bool) { return 0, false }, )(opt) // result = Some(84) ``` -------------------------------- ### IO Constructors Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Constructors for creating IO computations with varying numbers of parameters. ```APIDOC ## IO Constructors Represents a synchronous, pure, non-deterministic computation that never fails. ### Constructors ```go func NewIO[R any](f f0[R]) IO[R] func NewIO1[R any, A any](f f1[R, A]) IO1[R, A] func NewIO2[R any, A any, B any](f f2[R, A, B]) IO2[R, A, B] func NewIO3[R any, A any, B any, C any](f f3[R, A, B, C]) IO3[R, A, B, C] func NewIO4[R any, A any, B any, C any, D any](f f4[R, A, B, C, D]) IO4[R, A, B, C, D] func NewIO5[R any, A any, B any, C any, D any, E any](f f5[R, A, B, C, D, E]) IO5[R, A, B, C, D, E] ``` **Example:** ```go io := mo.NewIO(func() int { return 42 }) io1 := mo.NewIO1(func(x int) int { return x * 2 }) ``` ``` -------------------------------- ### Either3[T1, T2, T3] Constructors Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Construct Either3 types using NewEither3Arg1, NewEither3Arg2, and NewEither3Arg3 for three possible values. ```go // Constructors e1 := mo.NewEither3Arg1[string, int, bool]("error") e2 := mo.NewEither3Arg2[string, int, bool](42) e3 := mo.NewEither3Arg3[string, int, bool](true) ``` -------------------------------- ### SQL Scanner/Valuer for Option and Result Source: https://github.com/samber/mo/blob/master/_autodocs/07-types-and-utilities.md Implementations for Option[T] and Result[T] to be used with the database/sql package for scanning and valuing. ```go // Option[T] implements: func (o *Option[T]) Scan(src any) error func (o Option[T]) Value() (driver.Value, error) // Result[T] implements: func (o *Result[T]) Scan(src any) error func (o Result[T]) Value() (driver.Value, error) ``` -------------------------------- ### Executing Functions Based on Either3 Argument Source: https://github.com/samber/mo/blob/master/_autodocs/05-either3-4-5.md The ForEach method executes a specific function based on which of the three arguments is present in the Either3 instance. ```go e := mo.NewEither3Arg2[string, int, bool](42) e.ForEach( func(s string) { println("arg1:", s) }, func(i int) { println("arg2:", i) }, // executed func(b bool) { println("arg3:", b) }, ) ``` -------------------------------- ### Type Definitions Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Defines the structures for Future, IO, Task, and State, outlining their internal fields and types. ```go type Future[T any] struct { mu sync.Mutex cb func(func(T), func(error)) cancelCb func() next *Future[T] done chan struct{} doneOnce sync.Once result Result[T] } type IO[R any] struct { unsafePerform f0[R] } type Task[R any] struct { unsafePerform ff0[R] } type State[S any, A any] struct { run func(state S) (A, S) } ``` -------------------------------- ### Run IO Computations Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Execute IO computations synchronously using the Run method. The method takes arguments for IO1-5 types and returns the computed value. ```go func (io IO[R]) Run() R func (io IO1[R, A]) Run(a A) R func (io IO2[R, A, B]) Run(a A, b B) R // ... and so on for IO3-5 ``` ```go io := mo.NewIO(func() int { return 42 }) result := io.Run() // 42 io1 := mo.NewIO1(func(x int) int { return x * 2 }) result2 := io1.Run(21) // 42 ``` -------------------------------- ### Run State Computation Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Executes the stateful computation with an initial state and returns the result along with the modified state. ```go func (s State[S, A]) Run(state S) (A, S) ``` ```go incr := mo.NewState[int, int](func(state int) (int, int) { return state, state + 1 }) result, newState := incr.Run(5) // result = 5, newState = 6 ``` -------------------------------- ### IOEither Run Method Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Executes the IOEither computation synchronously and returns an Either result. ```APIDOC ## IOEither Run Method Executes the IOEither computation synchronously and returns an Either. ### Methods #### Run ```go func (io IOEither[R]) Run() Either[error, R] func (io IOEither1[R, A]) Run(a A) Either[error, R] // ... and so on for IOEither2-5 ``` **Returns:** `Either[error, R]` — Left(error) on failure, Right(value) on success **Example:** ```go io := mo.NewIOEither(func() (int, error) { return 42, nil }) either := io.Run() val, ok := either.Right() // val = 42, ok = true ``` ``` -------------------------------- ### Error Handling: Catch in Future Chains Source: https://github.com/samber/mo/blob/master/_autodocs/QUICK-REFERENCE.md Illustrates how to use the Catch function within Future chains to handle errors gracefully, providing fallback values or alternative error handling logic. ```go // Catch in Future chains future.Catch(func(err error) (T, error) { log.Println("Error:", err) return fallback, nil }) ``` -------------------------------- ### Option Constructors Source: https://github.com/samber/mo/blob/master/README.md These functions are used to create Option types. `Some` creates an Option with a value, while `None` creates an empty Option. `TupleToOption`, `EmptyableToOption`, and `PointerToOption` provide convenient ways to convert other types into Options. ```APIDOC ## Option Constructors - `mo.Some[T any]()` - `mo.None[T any]()` - `mo.TupleToOption[T1, T2 any](tuple [2]any) Option[T1] - `mo.EmptyableToOption[T any](value T) Option[T] - `mo.PointerToOption[T any](ptr *T) Option[T] ``` -------------------------------- ### Task Constructors Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Use these constructors to create Task instances from functions or IO operations. Task represents a pure, non-deterministic computation that never fails. ```go func NewTask[R any](f ff0[R]) Task[R] func NewTaskFromIO[R any](io IO[R]) Task[R] func NewTask1[R any, A any](f ff1[R, A]) Task1[R, A] func NewTaskFromIO1[R any, A any](io IO1[R, A]) Task1[R, A] // ... and so on for Task2-5 ``` -------------------------------- ### FlatMatch Option Value Source: https://github.com/samber/mo/blob/master/_autodocs/06-transformations-and-pipes.md Similar to Match, but the provided functions return Options instead of (value, bool) tuples. Requires importing the 'option' package. ```go func FlatMatch[I any, O any]( onValue func(I) mo.Option[O], onNone func() mo.Option[O], ) func(opt mo.Option[I]) mo.Option[O] ``` -------------------------------- ### Create a Successful Result with Ok Source: https://github.com/samber/mo/blob/master/_autodocs/02-result.md Use `Ok` to construct a Result that holds a successful value. This is typically used when an operation completes without errors. ```go package main import "github.com/samber/mo" func main() { res := mo.Ok(42) val, err := res.Get() // val = 42, err = nil } ``` -------------------------------- ### Foldable Generic Operations Source: https://github.com/samber/mo/blob/master/_autodocs/07-types-and-utilities.md Shows how to perform foldable generic operations by applying success or failure functions based on the state of an Option or Result type. ```go result := mo.Fold( someOption, func(v int) string { return "success" }, func(err error) string { return "failure" }, ) ``` -------------------------------- ### Error Handling with Result Type Source: https://github.com/samber/mo/blob/master/_autodocs/00-index.md Demonstrates how to handle potential errors using the `mo.Result` type. Use this pattern when a function can either return a successful value or an error. ```Go func divide(a, b int) mo.Result[int] { return mo.Try(func() (int, error) { if b == 0 { return 0, errors.New("division by zero") } return a / b, nil }) } result := divide(10, 2) val, err := result.Get() ``` -------------------------------- ### IO Run Method Source: https://github.com/samber/mo/blob/master/_autodocs/04-future-task-io.md Executes the IO computation synchronously and returns the result. ```APIDOC ## IO Run Method Executes the IO computation synchronously. ### Methods #### Run ```go func (io IO[R]) Run() R func (io IO1[R, A]) Run(a A) R func (io IO2[R, A, B]) Run(a A, b B) R // ... and so on for IO3-5 ``` **Example:** ```go io := mo.NewIO(func() int { return 42 }) result := io.Run() // 42 io1 := mo.NewIO1(func(x int) int { return x * 2 }) result2 := io1.Run(21) // 42 ``` ```