Skip to content

alex-lairan/monads

Repository files navigation

monads

Build Status

Monads for Crystal.

Inspired by https://github.com/dry-rb/dry-monads

Installation

Add this to your application's shard.yml:

dependencies:
  monads:
    github: alex-lairan/monads

Usage

require "monads"

Many monads exist.

Maybe(T)

The Maybe monad helps to avoid nil and chain instructions.

There are two kinds of Maybe, Just and Nothing.

Just(T)

This is just a value.

Monads::Just.new(5)

Nothing(T)

This is an absence of value.

Monads::Nothing(Int32).new

Either(E, T)

The Either monad helps to manage errors at the end of the chain of instructions.

There are two kinds of Either, Right and Left.

Right(T)

This is just a value.

Monads::Right.new("Hello world")

Left(E)

This is an error.

Monads::Left.new("User password is incorrect")

List(T)

The List monad helps to manipulate an Array like a monad.

Monads::List[1, 6, 4, 2]

head

head returns the first element wrapped within a Maybe.

tail

tail returns the list without the first element.

Try(T)

The Try monad is a layer between Object Oriented Exception and Fuctional Programming Monads. It can be transformed into a Maybe or an Either.

Task(T)

The Task monad is a parallelized Try monad. Its goal is to use the power of fibers with monads.

How to use a monad ?

Monads have some methods which help to chain instructions.

Try and Task monads should be translated into a Maybe(T) or an Either(Exception, T) one.

fmap

The fmap procedure modify the internal value of a monad.

This doesn't affect Nothing and Left monads.

Example:

value = Monads::Just.new(5)
  .fmap(->(x : Int32) { x.to_s })
  .fmap(->(x : String) { x + "12" })
  .fmap(->(x : String) { x.to_i })
  .value!
value.should eq(512)

bind

The bind procedure allows to create a whole new monad from the internal data of another.

This doesn't affect Nothing and Left monads.

Example:

value = Monads::Just.new(5)
  .bind(->(x : Int32) { Monads::Try(Int32).new(-> { x / 0}).to_maybe })
value.should eq(Monads::Nothing(Int32).new)

Development

Clone then let's go, no special requirements.

Contributing

  1. Fork it (https://github.com/alex-lairan/monads/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors