What is monads?
monads is a small, dependency-free library that brings monads to Crystal. It is inspired by Ruby's dry-monads.
A monad is a container for a value together with a consistent way to chain operations over that value. Instead of writing nested nil checks or scattering begin/rescue blocks across your code, you wrap a value once and then compose transformations that automatically short-circuit when something is absent or fails.
Why use it?
- Avoid
nil.Maybemakes the absence of a value explicit withJustandNothing, so you can never forget to handle it. - Handle errors without exceptions.
Eithercarries either a success (Right) or an error (Left) through a whole chain, letting you deal with the failure at the end. - Bridge exceptions and FP.
Tryruns code that may raise and turns the outcome into aMaybeor anEither.Taskdoes the same on a fiber for concurrency. - Treat arrays as monads.
Listwraps anArrayand gives itfmap/bindplus helpers likehead,tail, andsubsequences.
The shared interface
Every monad implements the same core operations, so once you learn them for one type they apply everywhere:
fmap— transform the value inside the monad.bind— transform the value into a whole new monad.fold— pattern-match on the two variants.
See Chaining Monads for the full tour, or jump straight to Getting Started.
A taste
crystal
require "monads"
Monads::Just.new(5)
.fmap(->(x : Int32) { x.to_s })
.fmap(->(x : String) { x + "12" })
.fmap(->(x : String) { x.to_i })
.value! # => 512