mo
mo copied to clipboard
🦄 Monads and popular FP abstractions, powered by Go 1.18+ Generics (Option, Result, Either...)
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/lo: A Lodash-style Go library based on Go 1.18+ Generics
- samber/do: A dependency injection toolkit based on Go 1.18+ Generics
Why this name?
I love short name for such utility library. This name is similar to "Monad Go" and no Go package currently uses this name.
💡 Features
We currently support the following data types:
Option[T](Maybe)Result[T]Either[A, B]Future[T]IO[T]IOEither[T]Task[T]TaskEither[T]State[S, A]
🚀 Install
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.
💡 Quick start
You can import mo using:
import (
"github.com/samber/mo"
)
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.
🤠 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.
Constructors:
Methods:
.IsPresent()doc.IsAbsent()doc.Size()doc.Get()doc.MustGet()doc.OrElse()doc.OrEmpty()doc.ForEach()doc.Match()doc.Map()doc.MapNone()doc.FlatMap()doc
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].
Constructors:
Methods:
.IsOk()doc.IsError()doc.Error()doc.Get()doc.MustGet()doc.OrElse()doc.OrEmpty()doc.ToEither()doc.ForEach()doc.Match()doc.Map()doc.MapErr()doc.FlatMap()doc
Either[L any, R any]
Either respresents a value of 2 possible types. An instance of Either is an instance of either A or B.
Constructors:
Methods:
.IsLeft()doc.IsRight()doc.Left()doc.Right()doc.MustLeft()doc.MustRight()doc.LeftOrElse()doc.RightOrElse()doc.LeftOrEmpty()doc.RightOrEmpty()doc.Swap()doc.ForEach()doc.Match()doc.MapLeft()doc.MapRight()doc
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:
Methods:
.Run()doc
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]
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]
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]
State represents a function (S) -> (A, S), where S is state, A is result.
Constructors:
Methods:
🛩 Benchmark
// @TODO
This library does not use reflect package. We don't expect overhead.
🤝 Contributing
- Ping me on twitter @samuelberthe (DMs, mentions, whatever :))
- Fork the project
- Fix open issues or request new features
Don't hesitate ;)
With Docker
docker-compose run --rm dev
Without Docker
# Install some dev dependencies
make tools
# Run tests
make test
# or
make watch-test
👤 Authors
- Samuel Berthe
💫 Show your support
Give a ⭐️ if this project helped you!
📝 License
Copyright © 2022 Samuel Berthe.
This project is MIT licensed.
