samber
mo
Go

πŸ¦„ Monads and popular FP abstractions, powered by Go 1.18+ Generics (Option, Result, Either...)

Last updated Jul 6, 2026
3.4k
Stars
114
Forks
16
Issues
+1
Stars/day
Attention Score
84
Language breakdown
Go 99.6%
Makefile 0.4%
β–Έ Files click to expand
README

mo - Monads

tag Go Version GoDoc Build Status Go report Coverage 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/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

πŸ’– Sponsored by:
dbos
DBOS - Durable workflow orchestration library for Go


image

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:

Methods: Other: Sub-package option (transformations and pipes):
  • option.Map()() doc
  • option.FlatMap()() doc
  • option.Match()() doc
  • option.FlatMatch()() doc
  • option.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:

Methods: Other: Sub-package result (transformations and pipes):
  • result.Map()() doc
  • result.FlatMap()() doc
  • result.Match()() doc
  • result.FlatMatch()() doc
  • result.Pipe1..Pipe10() docs

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: Sub-package either (transformations and pipes):
  • either.MapLeft()() doc
  • either.MapRight()() doc
  • either.Match()() doc
  • either.Swap()() doc
  • either.Pipe1..Pipe10() docs

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.NewEither3Arg1A, B, C - mo.NewEither3Arg2A, B, C - mo.NewEither3Arg3A, B, C - mo.NewEither4Arg1A, B, C, D - mo.NewEither4Arg2A, B, C, D - ...

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
- either3.Match()() doc - either3.MapArg1()() doc - either3.MapArg2()() doc - either3.MapArg3()() doc - either3.Pipe1..Pipe10() docs
  • either4 docs: https://pkg.go.dev/github.com/samber/mo/either4
- either4.Match()() doc - either4.MapArg1()() doc - either4.MapArg2()() doc - either4.MapArg3()() doc - either4.Pipe1..Pipe10() docs
  • either5 docs: https://pkg.go.dev/github.com/samber/mo/either5
- either5.Match()() doc - either5.MapArg1()() doc - either5.MapArg2()() doc - either5.MapArg3()() doc - either5.Pipe1..Pipe10() docs

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]

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
  • mo.NewIO1() doc
  • mo.NewIO2() doc
  • mo.NewIO3() doc
  • mo.NewIO4() doc
  • mo.NewIO5() doc
Methods:

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
  • mo.NewIOEither1() doc
  • mo.NewIOEither2() doc
  • mo.NewIOEither3() doc
  • mo.NewIOEither4() doc
  • mo.NewIOEither5() doc
Methods:

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
  • mo.NewTask1() doc
  • mo.NewTask2() doc
  • mo.NewTask3() doc
  • mo.NewTask4() doc
  • mo.NewTask5() doc
  • mo.NewTaskFromIO() doc
  • mo.NewTaskFromIO1() doc
  • mo.NewTaskFromIO2() doc
  • mo.NewTaskFromIO3() doc
  • mo.NewTaskFromIO4() doc
  • mo.NewTaskFromIO5() doc
Methods:

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
  • mo.NewTaskEitherFromIOEither() doc
Methods:

State[S any, A any]

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

Constructors:

  • mo.NewState() doc
  • mo.ReturnState() doc
Methods:

Foldable[T, U]

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

πŸ›© Benchmark

// @TODO

This library does not use reflect package. We don't expect overhead.

🀝 Contributing

Don't hesitate ;)
# Install some dev dependencies
make tools

Run tests

make test

or

make watch-test

πŸ‘€ Contributors

Contributors

πŸ’« Show your support

Give a ⭐️ if this project helped you!

GitHub Sponsors

πŸ“ License

Copyright Β© 2022 Samuel Berthe.

This project is MIT licensed.

πŸ”— More in this category

Β© 2026 GitRepoTrend Β· samber/mo Β· Updated daily from GitHub