typist
typist is a gem that allows you to define Algebraic Data Types (ADTs) in Ruby.
For a tutorial on ADTs, I recommend Learn You a Haskell's tutorial.
Features:
- A rich DSL that allows for idiomatic defintions of the data types
- Pattern matching
- Runtime support for incomplete pattern matches
- Class-load time support for invalid pattern matches
Planned Improvements:
- Type classes
- Optional runtime type checking
Installation
From the command line:
$ gem install typist
From a Gemfile:
gem 'typist'
Usage
To define a data type, first extend the Typist module in a top-level statement, or in the module in which you'd like your data type defined.
For example, to create a new data type in the Test module:
module Test
extend Typist
...
end
Once Typist has been extended, the data function will define a data type.
The following defines a new data type called Tree in the Test module:
module Test
extend Typist
data :Tree do
...
end
end
Type constructors may be defined using the constructor function.
module Test
extend Typist
data :Tree do
constructor :Leaf
constructor :Node, :value, :left, :right
end
end
Now, Tree::Leaf and Tree::Node are defined.
The arguments that come after the constructor name are the instance variables -- accessors are defined for each of them.
To create a new Leaf, run Tree.leaf.
To create a new Node, run Tree.node(:value => val, :right => Tree.leaf, :left => Tree.leaf).
Finally, the DSL allows the user to define and pattern match in functions.
The func method in the context of a data type declares a new function.
For example:
module Test
extend Typist
data :Tree do
constructor :Leaf
constructor :Node, :value, :left, :right
func :contains? do
match Tree::Leaf do |element|
false
end
match Tree::Node do |element|
case value <=> element
when -1
left.contains?(element)
when 1
right.contains?(element)
else
true
end
end
end
end
end
This defines #contains? method on Tree::Node and Tree::Leaf.
Example usage:
leaf = Tree.leaf
node = Tree.node(:value => 'a', :left => Tree.leaf, right => Tree.leaf)
leaf.contains?('a')
# => false
node.contains?('a')
# => true
Contributing
- Fork the repository
- Create a branch
- Add tests
- Commit your changes
- Push the branch
- DO NOT bump the version
- Submit a Pull Request

