# mo - Monads [![tag](https://img.shields.io/github/tag/samber/mo.svg)](https://github.com/samber/mo/releases) ![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.18-%23007d9c) [![GoDoc](https://godoc.org/github.com/samber/mo?status.svg)](https://pkg.go.dev/github.com/samber/mo) ![Build Status](https://github.com/samber/mo/actions/workflows/test.yml/badge.svg) [![Go report](https://goreportcard.com/badge/github.com/samber/mo)](https://goreportcard.com/report/github.com/samber/mo) [![Coverage](https://img.shields.io/codecov/c/github/samber/mo)](https://codecov.io/gh/samber/mo) [![License](https://img.shields.io/github/license/samber/mo)](./LICENSE) 🦄 **`samber/mo` brings monads and popular FP abstractions to Go projects. `samber/mo` uses the recent Go 1.18+ Generics.** **Inspired by:** - Scala - Rust - FP-TS **See also:** - [samber/lo](https://github.com/samber/lo): A Lodash-style Go library based on Go 1.18+ Generics - [samber/do](https://github.com/samber/do): A dependency injection toolkit based on Go 1.18+ Generics ![image](https://github.com/user-attachments/assets/1fc0f996-2a79-43e3-8db7-11e1409aca46) **Why this name?** I love **short name** for such utility library. This name is similar to "Monad Go" and no Go package uses this name. ## 💡 Features We currently support the following data types: - `Option[T]` (Maybe) - `Result[T]` - `Either[A, B]` - `EitherX[T1, ..., TX]` (With X between 3 and 5) - `Future[T]` - `IO[T]` - `IOEither[T]` - `Task[T]` - `TaskEither[T]` - `State[S, A]` ## 🚀 Install ```sh go get github.com/samber/mo@v1 ``` This library is v1 and follows SemVer strictly. No breaking changes will be made to exported APIs before v2.0.0. This library has no dependencies except the Go std lib. ## 💡 Quick start You can import `mo` using: ```go import ( "github.com/samber/mo" ) ``` Quick example using the `option` sub-package `Pipe3` to compose transformations: ```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] ``` Then use one of the helpers below: ```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 option3 := option1.Match( func(i int) (int, bool) { // when value is present return i * 2, true }, func() (int, bool) { // when value is absent return 0, false }, ) // Some(42) ``` More examples in [documentation](https://godoc.org/github.com/samber/mo). ### Tips for lazy developers I cannot recommend it, but in case you are too lazy for repeating `mo.` everywhere, you can import the entire library into the namespace. ```go import ( . "github.com/samber/mo" ) ``` I take no responsibility on this junk. 😁 💩 ## 🤠 Documentation and examples [GoDoc: https://godoc.org/github.com/samber/mo](https://godoc.org/github.com/samber/mo) ### Option[T any] `Option` is a container for an optional value of type `T`. If value exists, `Option` is of type `Some`. If the value is absent, `Option` is of type `None`. Implements: - `mo.Foldable[T, U]` Constructors: - `mo.Some()` [doc](https://pkg.go.dev/github.com/samber/mo#Some) - [play](https://go.dev/play/p/iqz2n9n0tDM) - `mo.None()` [doc](https://pkg.go.dev/github.com/samber/mo#None) - [play](https://go.dev/play/p/yYQPsYCSYlD) - `mo.TupleToOption()` [doc](https://pkg.go.dev/github.com/samber/mo#TupleToOption) - [play](https://go.dev/play/p/gkrg2pZwOty) - `mo.EmptyableToOption()` [doc](https://pkg.go.dev/github.com/samber/mo#EmptyableToOption) - [play](https://go.dev/play/p/GSpQQ-q-UES) - `mo.PointerToOption()` [doc](https://pkg.go.dev/github.com/samber/mo#PointerToOption) - [play](https://go.dev/play/p/yPVMj4DUb-I) Methods: - `.IsPresent()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.IsPresent) - [play](https://go.dev/play/p/nDqIaiihyCA) - `.IsSome()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.IsSome) - [play](https://go.dev/play/p/DyvGRy7fP9m) - `.IsAbsent()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.IsAbsent) - [play](https://go.dev/play/p/23e2zqyVOQm) - `.IsNone()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.IsNone) - [play](https://go.dev/play/p/EdqxKhborIP) - `.Size()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Size) - [play](https://go.dev/play/p/7ixCNG1E9l7) - `.Get()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Get) - [play](https://go.dev/play/p/0-JBa1usZRT) - `.MustGet()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MustGet) - [play](https://go.dev/play/p/RVBckjdi5WR) - `.OrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.OrElse) - [play](https://go.dev/play/p/TrGByFWCzXS) - `.OrEmpty()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.OrEmpty) - [play](https://go.dev/play/p/SpSUJcE-tQm) - `.ToPointer()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.ToPointer) - [play](https://go.dev/play/p/N43w92SM-Bs) - `.ForEach()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.ForEach) - `.Match()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Match) - [play](https://go.dev/play/p/1V6st3LDJsM) - `.Map()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Map) - [play](https://go.dev/play/p/mvfP3pcP_eJ) - `.MapNone()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MapNone) - [play](https://go.dev/play/p/_KaHWZ6Q17b) - `.MapValue()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MapValue) - `.FlatMap()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.FlatMap) - [play](https://go.dev/play/p/OXO-zJx6n5r) - `.MarshalJSON()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MarshalJSON) - `.UnmarshalJSON()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.UnmarshalJSON) - `.MarshalText()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MarshalText) - `.UnmarshalText()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.UnmarshalText) - `.MarshalBinary()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MarshalBinary) - `.UnmarshalBinary()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.UnmarshalBinary) - `.GobEncode()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.GobEncode) - `.GobDecode()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.GobDecode) - `.Scan()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Scan) - `.Value()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Value) Other: - `mo.Fold[T, U, R any](f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) R` [doc](https://pkg.go.dev/github.com/samber/mo#Fold) Sub-package `option` (transformations and pipes): - `option.Map()()` [doc](https://pkg.go.dev/github.com/samber/mo/option#Map) - `option.FlatMap()()` [doc](https://pkg.go.dev/github.com/samber/mo/option#FlatMap) - `option.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/option#Match) - `option.FlatMatch()()` [doc](https://pkg.go.dev/github.com/samber/mo/option#FlatMatch) - `option.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/option#Pipe1) ### Result[T any] `Result` respresent a result of an action having one of the following output: success or failure. An instance of `Result` is an instance of either `Ok` or `Err`. It could be compared to `Either[error, T]`. Implements: - `mo.Foldable[T, U]` Constructors: - `mo.Ok()` [doc](https://pkg.go.dev/github.com/samber/mo#Ok) - [play](https://go.dev/play/p/PDwADdzNoyZ) - `mo.Err()` [doc](https://pkg.go.dev/github.com/samber/mo#Err) - [play](https://go.dev/play/p/PDwADdzNoyZ) - `mo.Errf()` [doc](https://pkg.go.dev/github.com/samber/mo#Errf) - [play](https://go.dev/play/p/N43w92SM-Bs) - `mo.TupleToResult()` [doc](https://pkg.go.dev/github.com/samber/mo#TupleToResult) - [play](https://go.dev/play/p/KWjfqQDHQwa) - `mo.Try()` [doc](https://pkg.go.dev/github.com/samber/mo#Try) - [play](https://go.dev/play/p/ilOlQx-Mx42) Methods: - `.IsOk()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.IsOk) - [play](https://go.dev/play/p/sfNvBQyZfgU) - `.IsError()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.IsError) - [play](https://go.dev/play/p/xkV9d464scV) - `.Error()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.Error) - [play](https://go.dev/play/p/CSkHGTyiXJ5) - `.Get()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.Get) - [play](https://go.dev/play/p/8KyX3z6TuNo) - `.MustGet()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.MustGet) - [play](https://go.dev/play/p/8LSlndHoTAE) - `.OrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.OrElse) - [play](https://go.dev/play/p/MN_ULx0soi6) - `.OrEmpty()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.OrEmpty) - [play](https://go.dev/play/p/rdKtBmOcMLh) - `.ToEither()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.ToEither) - [play](https://go.dev/play/p/Uw1Zz6b952q) - `.ForEach()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.ForEach) - [play](https://go.dev/play/p/Z59EvNdWoRx) - `.Match()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.Match) - [play](https://go.dev/play/p/-_eFaLJ31co) - `.Map()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.Map) - [play](https://go.dev/play/p/-ndpN_b_OSc) - `.MapValue()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.MapValue) - [play](https://go.dev/play/p/qyyjUP4XbK2) - `.MapErr()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.MapErr) - [play](https://go.dev/play/p/WraZixg9GGf) - `.FlatMap()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.FlatMap) - [play](https://go.dev/play/p/Ud5QjZOqg-7) Other: - `mo.Fold[T, U, R any](f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) R` [doc](https://pkg.go.dev/github.com/samber/mo#Fold) - `mo.Do[T any](fn func() T) (result mo.Result[T])` [doc](https://pkg.go.dev/github.com/samber/mo#Do) Sub-package `result` (transformations and pipes): - `result.Map()()` [doc](https://pkg.go.dev/github.com/samber/mo/result#Map) - `result.FlatMap()()` [doc](https://pkg.go.dev/github.com/samber/mo/result#FlatMap) - `result.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/result#Match) - `result.FlatMatch()()` [doc](https://pkg.go.dev/github.com/samber/mo/result#FlatMatch) - `result.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/result#Pipe1) ### Either[L any, R any] `Either` represents a value of 2 possible types. An instance of `Either` is an instance of either `A` or `B`. Implements: - `mo.Foldable[T, U]` Constructors: - `mo.Left()` [doc](https://pkg.go.dev/github.com/samber/mo#Left) - `mo.Right()` [doc](https://pkg.go.dev/github.com/samber/mo#Right) Methods: - `.IsLeft()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.IsLeft) - `.IsRight()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.IsRight) - `.Left()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.Left) - `.Right()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.Right) - `.MustLeft()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.MustLeft) - `.MustRight()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.MustRight) - `.Unpack()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.Unpack) - `.LeftOrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.LeftOrElse) - `.RightOrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.RightOrElse) - `.LeftOrEmpty()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.LeftOrEmpty) - `.RightOrEmpty()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.RightOrEmpty) - `.Swap()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.Swap) - `.ForEach()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.ForEach) - `.Match()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.Match) - `.MapLeft()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.MapLeft) - `.MapRight()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.MapRight) Other: - `mo.Fold[T, U, R any](f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) R` [doc](https://pkg.go.dev/github.com/samber/mo#Fold) Sub-package `either` (transformations and pipes): - `either.MapLeft()()` [doc](https://pkg.go.dev/github.com/samber/mo/either#MapLeft) - `either.MapRight()()` [doc](https://pkg.go.dev/github.com/samber/mo/either#MapRight) - `either.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/either#Match) - `either.Swap()()` [doc](https://pkg.go.dev/github.com/samber/mo/either#Swap) - `either.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/either#Pipe1) ### EitherX[T1, ..., TX] (With X between 3 and 5) `EitherX` respresents a value of X possible types. For example, an `Either3` value is either `T1`, `T2` or `T3`. Constructors: - `mo.NewEitherXArgY()` [doc](https://pkg.go.dev/github.com/samber/mo#NewEither5Arg1). Eg: - `mo.NewEither3Arg1[A, B, C](A)` - `mo.NewEither3Arg2[A, B, C](B)` - `mo.NewEither3Arg3[A, B, C](C)` - `mo.NewEither4Arg1[A, B, C, D](A)` - `mo.NewEither4Arg2[A, B, C, D](B)` - ... Methods: - `.IsArgX()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.IsArg1) - `.ArgX()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.Arg1) - `.MustArgX()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.MustArg1) - `.Unpack()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.Unpack) - `.ArgXOrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.Arg1OrElse) - `.ArgXOrEmpty()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.Arg1OrEmpty) - `.ForEach()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.ForEach) - `.Match()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.Match) - `.MapArgX()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.MapArg1) Sub-packages `either3`, `either4`, `either5` (transformations and pipes): - either3 docs: https://pkg.go.dev/github.com/samber/mo/either3 - `either3.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/either3#Match) - `either3.MapArg1()()` [doc](https://pkg.go.dev/github.com/samber/mo/either3#MapArg1) - `either3.MapArg2()()` [doc](https://pkg.go.dev/github.com/samber/mo/either3#MapArg2) - `either3.MapArg3()()` [doc](https://pkg.go.dev/github.com/samber/mo/either3#MapArg3) - `either3.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/either3#Pipe1) - either4 docs: https://pkg.go.dev/github.com/samber/mo/either4 - `either4.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/either4#Match) - `either4.MapArg1()()` [doc](https://pkg.go.dev/github.com/samber/mo/either4#MapArg1) - `either4.MapArg2()()` [doc](https://pkg.go.dev/github.com/samber/mo/either4#MapArg2) - `either4.MapArg3()()` [doc](https://pkg.go.dev/github.com/samber/mo/either4#MapArg3) - `either4.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/either4#Pipe1) - either5 docs: https://pkg.go.dev/github.com/samber/mo/either5 - `either5.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/either5#Match) - `either5.MapArg1()()` [doc](https://pkg.go.dev/github.com/samber/mo/either5#MapArg1) - `either5.MapArg2()()` [doc](https://pkg.go.dev/github.com/samber/mo/either5#MapArg2) - `either5.MapArg3()()` [doc](https://pkg.go.dev/github.com/samber/mo/either5#MapArg3) - `either5.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/either5#Pipe1) ### Future[T any] `Future` represents a value which may or may not currently be available, but will be available at some point, or an exception if that value could not be made available. Constructors: - `mo.NewFuture()` [doc](https://pkg.go.dev/github.com/samber/mo#NewFuture) Methods: - `.Then()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Then) - `.Catch()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Catch) - `.Finally()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Finally) - `.Collect()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Collect) - `.Result()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Result) - `.Cancel()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Cancel) ### IO[T any] `IO` represents a non-deterministic synchronous computation that can cause side effects, yields a value of type `R` and never fails. Constructors: - `mo.NewIO()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO) - `mo.NewIO1()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO1) - `mo.NewIO2()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO2) - `mo.NewIO3()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO3) - `mo.NewIO4()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO4) - `mo.NewIO5()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO5) Methods: - `.Run()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Run) ### IOEither[T any] `IO` represents a non-deterministic synchronous computation that can cause side effects, yields a value of type `R` and can fail. Constructors: - `mo.NewIOEither()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither) - `mo.NewIOEither1()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither1) - `mo.NewIOEither2()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither2) - `mo.NewIOEither3()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither3) - `mo.NewIOEither4()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither4) - `mo.NewIOEither5()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither5) Methods: - `.Run()` [doc](https://pkg.go.dev/github.com/samber/mo#IOEither.Run) ### Task[T any] `Task` represents a non-deterministic asynchronous computation that can cause side effects, yields a value of type `R` and never fails. Constructors: - `mo.NewTask()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask) - `mo.NewTask1()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask1) - `mo.NewTask2()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask2) - `mo.NewTask3()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask3) - `mo.NewTask4()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask4) - `mo.NewTask5()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask5) - `mo.NewTaskFromIO()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO) - `mo.NewTaskFromIO1()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO1) - `mo.NewTaskFromIO2()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO2) - `mo.NewTaskFromIO3()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO3) - `mo.NewTaskFromIO4()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO4) - `mo.NewTaskFromIO5()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO5) Methods: - `.Run()` [doc](https://pkg.go.dev/github.com/samber/mo#Task.Run) ### TaskEither[T any] `TaskEither` represents a non-deterministic asynchronous computation that can cause side effects, yields a value of type `R` and can fail. Constructors: - `mo.NewTaskEither()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskEither) - `mo.NewTaskEitherFromIOEither()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskEitherFromIOEither) Methods: - `.Run()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Run) - `.OrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.OrElse) - `.Match()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Match) - `.TryCatch()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.TryCatch) - `.ToTask()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.ToTask) - `.ToEither()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.ToEither) ### State[S any, A any] `State` represents a function `(S) -> (A, S)`, where `S` is state, `A` is result. Constructors: - `mo.NewState()` [doc](https://pkg.go.dev/github.com/samber/mo#NewState) - `mo.ReturnState()` [doc](https://pkg.go.dev/github.com/samber/mo#ReturnState) Methods: - `.Run()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Run) - `.Get()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Get) - `.Modify()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Modify) - `.Put()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Put) ### Foldable[T, U] Foldable represents a type that can be folded into a single value based on its state. - `mo.Fold[T, U, R any](f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) R` [doc](https://pkg.go.dev/github.com/samber/mo#Fold) ## 🛩 Benchmark // @TODO This library does not use `reflect` package. We don't expect overhead. ## 🤝 Contributing - Ping me on Twitter [@samuelberthe](https://twitter.com/samuelberthe) (DMs, mentions, whatever :)) - Fork the [project](https://github.com/samber/mo) - Fix [open issues](https://github.com/samber/mo/issues) or request new features Don't hesitate ;) ```bash # Install some dev dependencies make tools # Run tests make test # or make watch-test ``` ## 👤 Contributors ![Contributors](https://contrib.rocks/image?repo=samber/mo) ## 💫 Show your support Give a ⭐️ if this project helped you! [![GitHub Sponsors](https://img.shields.io/github/sponsors/samber?style=for-the-badge)](https://github.com/sponsors/samber) ## 📝 License Copyright © 2022 [Samuel Berthe](https://github.com/samber). This project is [MIT](./LICENSE) licensed.