Mo
🦄 Monads and popular FP abstractions, powered by Go 1.18+ Generics (Option, Result, Either...)
Install / Use
/learn @samber/MoREADME
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
- samber/cc-skills-golang: AI Agent Skills for Golang
<div align="center"> <sup><b>💖 Sponsored by:</b></sup> <br> <a href="https://www.dbos.dev/?utm_campaign=gh-smbr"> <div> <img width="200" alt="dbos" src="https://github.com/user-attachments/assets/d583cb62-7735-4d3c-beb7-e6ef1a5faf49" /> </div> <div> DBOS - Durable workflow orchestration library for Go </div> </a> </div>
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
go get github.com/samber/mo@v1
# AI Agent Skill
npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-mo
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:
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
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
GoDoc: 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 - 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]
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:
