Skip to content
ADTs for Ruby
Ruby
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
examples
lib
spec
.gitignore
.rspec
CHANGELOG.md
README.md
Rakefile
TODO
adt.gemspec

README.md

ADT

A library for declaring algebraic data types in Ruby.

Usage

gem install adt

ADT provides a DSL for specifying the cases in an algebraic data type.

require 'adt'
class ValidatedValue
  extend ADT
  cases do
    missing
    invalid(:reason)
    ok(:value)
  end
end

# An Enumeration (nullary constructors only)
class State
  extend ADT
  cases do
    snafu
    smoking # 'Nullary contructor' means it takes no arguments
  end
end

What you now have:

  • Constructors for each of the cases: Type.case(arg)
  • A fold method, for matching on all the cases.
  • A good #== and #inspect implementation
  • #case? and #when__case_(handle_case_proc, default_proc) for dealing with a single case

Check the documentation for more information.

Usage examples

Construction:

# Create values
mine = ValidatedValue.ok(5)
missing = ValidatedValue.missing
invalid = ValidatedValue.invalid("Wrong number!")

Folding:

# Define operations on a value, only the proc matching the value's case will be 
# executed
mine.fold(
    proc { |value| value },
    proc { "missing default" }
    proc { |reason| raise "gah. Invalid is terrible" }
)

# Use an alias to #fold, named after the type:
mine.validated_value(
    :ok => proc { |value| value },
    :missing => proc { "missing default " },
    :invalid => proc { |reason| raise "gah. Invalid is terrible!" }
)

Support methods:

mine.ok? # <= true
mine.when_missing(proc { "I'm missing!" }, proc { "It's okay I'm around" })

# == does what you expect.
mine == ValidatedValue.missing # <= false
mine == ValidatedValue.ok(5) # <= true

# <=> 
ValidatedValue.ok(5) <=> ValidatedValue.ok(3) # <= 1 # Ordering is by the inner value(s), if the cases match
ValidatedValue.ok(5) <=> ValidatedValue.missing # <= 1 # Otherwise it is by increasing order in which the cases are defined

# to_a
ValidatedValue.ok(5).to_a == [5]
ValidatedValue.missing.to_a = []

# Inspect looks good.
mine.inspect # <= "#<ValidatedValue ok value:5>"

For the enumeration only:

State.all_values # <= [State.snafu, State.smoking]
State.snafu.to_i # <= 1
State.from_i(2) # <= State.smoking

Case info:

State.snafu.case_name == "snafu"
ValidatedValue.ok(3).case_arity == 1
State.snafu.case_index = 2

More Information on ADTs

Something went wrong with that request. Please try again.