samber/mo
{ "createdAt": "2022-05-17T23:07:48Z", "defaultBranch": "master", "description": "🦄 Monads and popular FP abstractions, powered by Go 1.18+ Generics (Option, Result, Either...)", "fullName": "samber/mo", "homepage": "https://pkg.go.dev/github.com/samber/mo", "language": "Go", "name": "mo", "pushedAt": "2025-11-25T10:15:02Z", "stargazersCount": 3222, "topics": [ "cats", "either", "fp", "functional", "future", "generics", "go", "golang", "io", "maybe", "monad", "monoid", "option", "optional", "programming", "result", "state", "task", "typesafe" ], "updatedAt": "2025-11-27T06:43:45Z", "url": "https://github.com/samber/mo"}mo - Monads
Section titled “mo - Monads”🦄 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/ro: Reactive Programming for Go: declarative and composable API for event-driven applications
- samber/lo: A Lodash-style Go library based on Go 1.18+ Generics
- samber/do: A dependency injection toolkit based on Go 1.18+ Generics
💖 Support This Project
I’m going all-in on open-source for the coming months.
Help sustain development: Become an individual sponsor or join as a corporate sponsor.
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
Section titled “💡 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
Section titled “🚀 Install”go get github.com/samber/mo@v1This 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
Section titled “💡 Quick start”You can import mo using:
import ( "github.com/samber/mo")Quick example using the option sub-package Pipe3 to compose transformations:
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:
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.
Tips for lazy developers
Section titled “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.
import ( . "github.com/samber/mo")I take no responsibility on this junk. 😁 💩
🤠 Documentation and examples
Section titled “🤠 Documentation and examples”GoDoc: https://godoc.org/github.com/samber/mo
Option[T any]
Section titled “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 - playmo.None()doc - playmo.TupleToOption()doc - playmo.EmptyableToOption()doc - playmo.PointerToOption()doc - play
Methods:
.IsPresent()doc - play.IsSome()doc - play.IsAbsent()doc - play.IsNone()doc - play.Size()doc - play.Get()doc - play.MustGet()doc - play.OrElse()doc - play.OrEmpty()doc - play.ToPointer()doc - play.ForEach()doc.Match()doc - play.Map()doc - play.MapNone()doc - play.MapValue()doc.FlatMap()doc - play.MarshalJSON()doc.UnmarshalJSON()doc.MarshalText()doc.UnmarshalText()doc.MarshalBinary()doc.UnmarshalBinary()doc.GobEncode()doc.GobDecode()doc.Scan()doc.Value()doc
Other:
mo.Fold[T, U, R any]!(f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) Rdoc
Sub-package option (transformations and pipes):
option.Map()()docoption.FlatMap()()docoption.Match()()docoption.FlatMatch()()docoption.Pipe1..Pipe10()docs
Result[T any]
Section titled “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 - playmo.Err()doc - playmo.Errf()doc - playmo.TupleToResult()doc - playmo.Try()doc - play
Methods:
.IsOk()doc - play.IsError()doc - play.Error()doc - play.Get()doc - play.MustGet()doc - play.OrElse()doc - play.OrEmpty()doc - play.ToEither()doc - play.ForEach()doc - play.Match()doc - play.Map()doc - play.MapValue()doc - play.MapErr()doc - play.FlatMap()doc - play
Other:
mo.Fold[T, U, R any]!(f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) Rdocmo.Do[T any]!(fn func() T) (result mo.Result[T])doc
Sub-package result (transformations and pipes):
result.Map()()docresult.FlatMap()()docresult.Match()()docresult.FlatMatch()()docresult.Pipe1..Pipe10()docs
Either[L any, R any]
Section titled “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:
Methods:
.IsLeft()doc.IsRight()doc.Left()doc.Right()doc.MustLeft()doc.MustRight()doc.Unpack()doc.LeftOrElse()doc.RightOrElse()doc.LeftOrEmpty()doc.RightOrEmpty()doc.Swap()doc.ForEach()doc.Match()doc.MapLeft()doc.MapRight()doc
Other:
mo.Fold[T, U, R any]!(f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) Rdoc
Sub-package either (transformations and pipes):
either.MapLeft()()doceither.MapRight()()doceither.Match()()doceither.Swap()()doceither.Pipe1..Pipe10()docs
EitherX[T1, …, TX] (With X between 3 and 5)
Section titled “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. 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.ArgX()doc.MustArgX()doc.Unpack()doc.ArgXOrElse()doc.ArgXOrEmpty()doc.ForEach()doc.Match()doc.MapArgX()doc
Sub-packages either3, either4, either5 (transformations and pipes):
-
either3 docs: https://pkg.go.dev/github.com/samber/mo/either3
-
either4 docs: https://pkg.go.dev/github.com/samber/mo/either4
-
either5 docs: https://pkg.go.dev/github.com/samber/mo/either5
Future[T any]
Section titled “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
Methods:
IO[T any]
Section titled “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:
Methods:
.Run()doc
IOEither[T any]
Section titled “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()docmo.NewIOEither1()docmo.NewIOEither2()docmo.NewIOEither3()docmo.NewIOEither4()docmo.NewIOEither5()doc
Methods:
.Run()doc
Task[T any]
Section titled “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()docmo.NewTask1()docmo.NewTask2()docmo.NewTask3()docmo.NewTask4()docmo.NewTask5()docmo.NewTaskFromIO()docmo.NewTaskFromIO1()docmo.NewTaskFromIO2()docmo.NewTaskFromIO3()docmo.NewTaskFromIO4()docmo.NewTaskFromIO5()doc
Methods:
.Run()doc
TaskEither[T any]
Section titled “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:
Methods:
State[S any, A any]
Section titled “State[S any, A any]”State represents a function (S) -> (A, S), where S is state, A is result.
Constructors:
Methods:
Foldable[T, U]
Section titled “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) Rdoc
🛩 Benchmark
Section titled “🛩 Benchmark”// @TODO
This library does not use reflect package. We don’t expect overhead.
🤝 Contributing
Section titled “🤝 Contributing”- Ping me on Twitter @samuelberthe (DMs, mentions, whatever :))
- Fork the project
- Fix open issues or request new features
Don’t hesitate ;)
# Install some dev dependenciesmake tools
# Run testsmake test# ormake watch-test👤 Contributors
Section titled “👤 Contributors”💫 Show your support
Section titled “💫 Show your support”Give a ⭐️ if this project helped you!
📝 License
Section titled “📝 License”Copyright © 2022 Samuel Berthe.
This project is [MIT]!(./LICENSE) licensed.