typist 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2757d8cd18bfb8ebf6112c05e260f20805f6fb4d
4
+ data.tar.gz: b5a017f46fba7063f1d8661bfadc2dca4876f0bd
5
+ SHA512:
6
+ metadata.gz: 175cca390f72642c375d281d836c90a38bbad5bb774049babbb17b3a626a2e74fc1fe51971cb6af2549f867dad42027cfdb12ef33d37728077b0bf8cccc96086
7
+ data.tar.gz: e0502bdfa7442b48ae9a7baae0985c4f49c353bbeedcccf759f03e46755fbd18cc3f81573878803c06c42d1a396e414295fd66b6149d20af74ec799c01d0d6ee
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ *.gem
3
+ Gemfile.lock
4
+ coverage/
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3-p484
5
+ - 2.0.0-p353
6
+ - 2.1.0
7
+ - jruby-1.7.9
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # typist
2
+
3
+ [![Build Status](https://travis-ci.org/nahiluhmot/typist.png?branch=master)](https://travis-ci.org/nahiluhmot/typist)
4
+ [![Code Climate](https://codeclimate.com/github/nahiluhmot/typist.png)](https://codeclimate.com/github/nahiluhmot/typist)
5
+
6
+ `typist` is a gem that allows you to define Algebraic Data Types (ADTs) in Ruby.
7
+ For a tutorial on ADTs, I recommend [Learn You a Haskell's tutorial](http://learnyouahaskell.com/making-our-own-types-and-typeclasses).
8
+
9
+ Features:
10
+
11
+ * A rich DSL that allows for idiomatic defintions of the data types
12
+ * Pattern matching
13
+ * Runtime support for incomplete pattern matches
14
+ * Class-load time support for invalid pattern matches
15
+
16
+ Planned Improvements:
17
+
18
+ * Type classes
19
+ * Optional runtime type checking
20
+
21
+ # Installation
22
+
23
+ From the command line:
24
+
25
+ ```shell
26
+ $ gem install typist
27
+ ```
28
+
29
+ From a Gemfile:
30
+
31
+ ```ruby
32
+ gem 'typist'
33
+ ```
34
+
35
+ # Usage
36
+
37
+ 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.
38
+ For example, to create a new data type in the `Test` module:
39
+
40
+ ```ruby
41
+ module Test
42
+ extend Typist
43
+
44
+ ...
45
+ end
46
+ ```
47
+
48
+ Once `Typist` has been extended, the `data` function will define a data type.
49
+ The following defines a new data type called `Tree` in the `Test` module:
50
+
51
+ ```ruby
52
+ module Test
53
+ extend Typist
54
+
55
+ data :Tree do
56
+ ...
57
+ end
58
+ end
59
+ ```
60
+
61
+ Type constructors may be defined using the `constructor` function.
62
+
63
+ ```ruby
64
+ module Test
65
+ extend Typist
66
+
67
+ data :Tree do
68
+ constructor :Leaf
69
+ constructor :Node, :value, :left, :right
70
+ end
71
+ end
72
+ ```
73
+
74
+ Now, `Tree::Leaf` and `Tree::Node` are defined.
75
+ The arguments that come after the constructor name are the instance variables -- accessors are defined for each of them.
76
+ To create a new Leaf, run `Tree.leaf`.
77
+ To create a new Node, run `Tree.node(:value => val, :right => Tree.leaf, :left => Tree.leaf)`.
78
+
79
+ Finally, the DSL allows the user to define and pattern match in functions.
80
+ The `func` method in the context of a data type declares a new function.
81
+ For example:
82
+
83
+ ```ruby
84
+ module Test
85
+ extend Typist
86
+
87
+ data :Tree do
88
+ constructor :Leaf
89
+ constructor :Node, :value, :left, :right
90
+
91
+ func :contains? do
92
+ match Tree::Leaf do |element|
93
+ false
94
+ end
95
+
96
+ match Tree::Node do |element|
97
+ case value <=> element
98
+ when -1
99
+ left.contains?(element)
100
+ when 1
101
+ right.contains?(element)
102
+ else
103
+ true
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ ```
110
+
111
+ This defines `#contains?` method on `Tree::Node` and `Tree::Leaf`.
112
+ Example usage:
113
+
114
+ ```ruby
115
+ leaf = Tree.leaf
116
+ node = Tree.node(:value => 'a', :left => Tree.leaf, right => Tree.leaf)
117
+
118
+ leaf.contains?('a')
119
+ # => false
120
+
121
+ node.contains?('a')
122
+ # => true
123
+ ```
124
+
125
+ # Contributing
126
+
127
+ 1. Fork the repository
128
+ 2. Create a branch
129
+ 3. Add tests
130
+ 4. Commit your changes
131
+ 5. Push the branch
132
+ 6. DO NOT bump the version
133
+ 7. Submit a Pull Request
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+
3
+ require 'rake'
4
+ require 'typist'
5
+ require 'rspec/core/rake_task'
6
+ require 'cane/rake_task'
7
+
8
+ task :default => [:spec, :quality]
9
+
10
+ RSpec::Core::RakeTask.new(:spec) do |t|
11
+ t.pattern = 'spec/**/*_spec.rb'
12
+ end
13
+
14
+ Cane::RakeTask.new(:quality) do |cane|
15
+ cane.canefile = '.cane'
16
+ end
@@ -0,0 +1,48 @@
1
+ # This class represents a data-type contstructor.
2
+ class Typist::Constructor
3
+ attr_reader :name, :vars
4
+
5
+ # Create a new constructor with the given name and instance variable(s).
6
+ def initialize(name, *vars)
7
+ @name = name
8
+ @vars = vars
9
+ end
10
+
11
+ # Get the Class that this Constructor defines.
12
+ def get_class
13
+ @class ||= Class.new
14
+ end
15
+
16
+ # Turn the constructor into a class definition, then define a convenience
17
+ # method in the given module.
18
+ def define!(context)
19
+ get_class.tap do |klass|
20
+ define_class(context, klass)
21
+ define_initializer(context, klass)
22
+ end
23
+ end
24
+
25
+ def define_class(context, klass)
26
+ attrs = vars
27
+ klass.instance_eval do
28
+ include context
29
+ attr_accessor(*attrs)
30
+
31
+ define_method(:initialize) do |hash = {}|
32
+ hash.each { |key, val| instance_variable_set(:"@#{key}", val) }
33
+ end
34
+ end
35
+ context.const_set(name, klass)
36
+ end
37
+ private :define_class
38
+
39
+ def define_initializer(context, klass)
40
+ method_name = Typist::Util.snakeify(name)
41
+
42
+ context.module_eval do
43
+ define_method(method_name) { |*args| klass.new(*args) }
44
+ module_function method_name
45
+ end
46
+ end
47
+ private :define_initializer
48
+ end
@@ -0,0 +1,38 @@
1
+ # Instances of this class may be included like a module.
2
+ class Typist::Data
3
+ attr_reader :name, :constructors, :funcs, :block
4
+
5
+ # Create a new data type with the given name. The block will be evaluated in
6
+ # the context of the new instance.
7
+ def initialize(name, &block)
8
+ @name = name
9
+ @constructors = []
10
+ @funcs = []
11
+ @block = block
12
+ end
13
+
14
+ # Define a constructor for this data type.
15
+ def constructor(*args, &block)
16
+ constructors << Typist::Constructor.new(*args, &block)
17
+ end
18
+
19
+ # Define a function which may pattern-matched against
20
+ def func(*args, &block)
21
+ funcs << Typist::Func.new(*args, &block)
22
+ end
23
+
24
+ # Get the module that is defined.
25
+ def get_module
26
+ @module ||= Module.new
27
+ end
28
+
29
+ # Define the module, constructors, and functions.
30
+ def define!(mod = Kernel)
31
+ get_module.tap do |context|
32
+ mod.const_set(name, context)
33
+ instance_eval(&block) unless block.nil?
34
+ constructors.each { |constructor| constructor.define!(context) }
35
+ funcs.each { |func| func.define!(context) }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ # This module holds all errors thrown in the gem.
2
+ module Typist::Error
3
+ # This class is never thrown, but can be used as a catch-all.
4
+ class BaseError < StandardError; end
5
+
6
+ # This is thrown when a pattern match is not exhaustive.
7
+ class PatternError < BaseError; end
8
+
9
+ # This is thrown when an invalid type contstructor is matched against.
10
+ class MatchError < BaseError; end
11
+ end
@@ -0,0 +1,49 @@
1
+ # This class defines the `func` DSL.
2
+ class Typist::Func
3
+ attr_reader :name, :matches, :block
4
+
5
+ # Create a new function with the given name (String/Symbol). If a block is
6
+ # given, it will be evaluated in the context of the new instance.
7
+ def initialize(name, &block)
8
+ @name = name
9
+ @matches = {}
10
+ @block = block
11
+ end
12
+
13
+ # Pattern match against the given class.
14
+ def match(klass, &block)
15
+ matches[klass] = block
16
+ end
17
+
18
+ # Given a module define this function, plus the pattern matches for all of its
19
+ # subclasses.
20
+ def define!(context)
21
+ instance_eval(&block) unless block.nil?
22
+ define_base(context)
23
+ matches.each { |klass, block| define_match(context, klass, &block) }
24
+ context
25
+ end
26
+
27
+ def define_base(context)
28
+ method_name = name
29
+
30
+ context.class_eval do
31
+ define_method(method_name) do |*_, &_|
32
+ raise Typist::Error::PatternError,
33
+ "Patterns not exhaustive in #{context}##{method_name}"
34
+ end
35
+ end
36
+ end
37
+ private :define_base
38
+
39
+ def define_match(context, klass, &block)
40
+ unless klass.ancestors.include?(context)
41
+ raise Typist::Error::MatchError,
42
+ "#{klass} is not a valid constructor for #{context}"
43
+ end
44
+
45
+ method_name = name
46
+ klass.class_eval { define_method(method_name, &block) }
47
+ end
48
+ private :define_match
49
+ end
@@ -0,0 +1,15 @@
1
+ # This module contains common logic used throughout the gem.
2
+ module Typist::Util
3
+ # Convert a CamelCase String to snake_case. Shamelessly stolen from
4
+ # ActiveSupport.
5
+ def snakeify(string)
6
+ string.to_s.
7
+ gsub(/::/, '/').
8
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
9
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
10
+ tr("-", "_").
11
+ downcase
12
+ end
13
+
14
+ module_function :snakeify
15
+ end
@@ -0,0 +1,4 @@
1
+ # This file holds version information for the gem.
2
+ module Typist
3
+ VERSION = '0.0.1'
4
+ end
data/lib/typist.rb ADDED
@@ -0,0 +1,16 @@
1
+ # This is the top level module for the gem, used as a namespace and as a
2
+ # location for high-level functions.
3
+ module Typist
4
+ autoload :Constructor, 'typist/constructor'
5
+ autoload :Data, 'typist/data'
6
+ autoload :Error, 'typist/error'
7
+ autoload :Func, 'typist/func'
8
+ autoload :Util, 'typist/util'
9
+
10
+ # Define a new data type.
11
+ def data(*args, &block)
12
+ Data.new(*args, &block).define!(self.is_a?(Module) ? self : Kernel)
13
+ end
14
+
15
+ module_function :data
16
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe Typist::Constructor do
4
+ describe '#initialize' do
5
+ subject { described_class.new(:Node, :value, :left, :right) }
6
+
7
+ it 'sets the @name instance variable' do
8
+ subject.name.should == :Node
9
+ end
10
+
11
+ it 'sets the @vars instance variable' do
12
+ subject.vars.should == [:value, :left, :right]
13
+ end
14
+ end
15
+
16
+ describe '#get_class' do
17
+ subject { described_class.new(:Leaf) }
18
+
19
+ it 'returns a Class' do
20
+ subject.get_class.should be_a Class
21
+ end
22
+ end
23
+
24
+ describe '#define!' do
25
+ subject { Typist::Constructor.new(:TestClass, :arg1, :arg2) }
26
+ let(:mod) { Module.new }
27
+
28
+ before { subject.define!(mod) }
29
+
30
+ describe 'the defined class' do
31
+ let(:instance) {
32
+ mod::TestClass.new(:arg1 => ?a, :arg2 => ?b, :arg3 => ?c)
33
+ }
34
+
35
+ it 'has each @var as an accessor' do
36
+ instance.should respond_to(:arg1)
37
+ instance.should respond_to(:arg2)
38
+ instance.should_not respond_to(:arg3)
39
+ end
40
+
41
+ it 'accepts a hash in its initializer which sets instance variables' do
42
+ instance.instance_variable_get(:@arg1).should == ?a
43
+ instance.instance_variable_get(:@arg2).should == ?b
44
+ instance.instance_variable_get(:@arg3).should == ?c
45
+ end
46
+
47
+ it 'includes the given module' do
48
+ subject.get_class.ancestors.should include(mod)
49
+ end
50
+ end
51
+
52
+ describe 'the given module' do
53
+ let(:instance) { mod.test_class(:arg1 => 1, :arg2 => 2) }
54
+
55
+ it 'defines a method to create an instance of the defined class' do
56
+ instance.should be_a mod::TestClass
57
+ instance.arg1.should == 1
58
+ instance.arg2.should == 2
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,144 @@
1
+ require 'spec_helper'
2
+
3
+ describe Typist::Data do
4
+ describe '#initialize' do
5
+ context 'when no block is given' do
6
+ subject { described_class.new(:Test) }
7
+
8
+ it 'sets the @name' do
9
+ subject.name.should == :Test
10
+ end
11
+
12
+ it 'sets the @constructors to []' do
13
+ subject.constructors.should be_empty
14
+ end
15
+
16
+ it 'sets the @funcs to []' do
17
+ subject.funcs.should be_empty
18
+ end
19
+ end
20
+
21
+ context 'when a block is given' do
22
+ subject {
23
+ described_class.new(:Test) do
24
+ instance_variable_set(:@test_var, true)
25
+ end
26
+ }
27
+ end
28
+ end
29
+
30
+ describe '#constructor' do
31
+ subject { described_class.new(:BinaryTree) }
32
+
33
+ it 'adds a constructor' do
34
+ expect { subject.constructor(:Leaf) }
35
+ .to change { subject.constructors.length }.by(1)
36
+
37
+ subject.constructors.should be_all { |constructor|
38
+ constructor.is_a?(Typist::Constructor)
39
+ }
40
+ end
41
+ end
42
+
43
+ describe '#func' do
44
+ subject { described_class.new(:Trie) }
45
+
46
+ it 'adds a constructor' do
47
+ expect { subject.func(:empty) }
48
+ .to change { subject.funcs.length }.by(1)
49
+
50
+ subject.funcs.should be_all { |funcs|
51
+ funcs.is_a?(Typist::Func)
52
+ }
53
+ end
54
+ end
55
+
56
+ describe '#get_module' do
57
+ subject { described_class.new(:Set) }
58
+
59
+ it 'returns a module' do
60
+ subject.get_module.should be_a(Module)
61
+ end
62
+ end
63
+
64
+ describe '#define!' do
65
+ subject! {
66
+ defined?(Tree) ? Tree : Typist::Data.new(:Tree) do
67
+ constructor :Leaf
68
+ constructor :Node, :value, :left, :right
69
+
70
+ func :empty? do
71
+ match(Tree::Leaf) { true }
72
+ match(Tree::Node) { false }
73
+ end
74
+
75
+ func :size do
76
+ match(Tree::Leaf) { 0 }
77
+ match(Tree::Node) { (left.size + right.size).succ }
78
+ end
79
+
80
+ func :contains? do
81
+ match(Tree::Leaf) { |_| false }
82
+
83
+ match(Tree::Node) do |element|
84
+ case value <=> element
85
+ when -1
86
+ left.contains?(value)
87
+ when 1
88
+ right.contains?(value)
89
+ else
90
+ true
91
+ end
92
+ end
93
+ end
94
+
95
+ func :== do
96
+ match(Tree::Leaf) { |tree| tree.is_a?(Tree::Leaf) }
97
+ match(Tree::Node) do |tree|
98
+ [
99
+ tree.is_a?(Tree::Node),
100
+ value == tree.value,
101
+ left == tree.left,
102
+ right == tree.right
103
+ ].all?
104
+ end
105
+ end
106
+ end.tap(&:define!)
107
+ }
108
+
109
+ let(:leaf) { Tree.leaf }
110
+ let(:node) {
111
+ Tree.node(
112
+ :value => 4,
113
+ :left => Tree.leaf,
114
+ :right => Tree.leaf
115
+ )
116
+ }
117
+
118
+ it 'defines convenience methods' do
119
+ Tree.should respond_to(:node)
120
+ Tree.should respond_to(:leaf)
121
+ end
122
+
123
+ it 'defines each constructor' do
124
+ Tree::Node.should include(Tree)
125
+ Tree::Leaf.should include(Tree)
126
+
127
+ node.value.should == 4
128
+ node.left.should == Tree.leaf
129
+ node.right.should == Tree.leaf
130
+ end
131
+
132
+ it 'defines functions on the constructors' do
133
+ leaf.should be_empty
134
+ node.should_not be_empty
135
+
136
+ leaf.contains?(4).should be_false
137
+ node.contains?(4).should be_true
138
+ node.contains?(5).should be_false
139
+
140
+ leaf.size.should == 0
141
+ node.size.should == 1
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe Typist::Func do
4
+ describe '#initialize' do
5
+ context 'when there is no block' do
6
+ subject { described_class.new(:a_function) }
7
+
8
+ it 'sets the @name instance variable to the first argument' do
9
+ subject.name.should == :a_function
10
+ end
11
+
12
+ it 'has no matches intially' do
13
+ subject.matches.should be_empty
14
+ end
15
+ end
16
+
17
+ context 'when there is a block' do
18
+ subject {
19
+ Typist::Func.new(:this_function) do
20
+ @test_var = 15
21
+ end
22
+ }
23
+ end
24
+ end
25
+
26
+ describe '#match' do
27
+ subject { described_class.new(:test_func) }
28
+
29
+ before { subject.match(Fixnum) { :it_works } }
30
+
31
+ it 'adds that to the @matches hash' do
32
+ subject.matches[Fixnum].call.should == :it_works
33
+ end
34
+ end
35
+
36
+ describe '#define!' do
37
+
38
+ context 'when an invalid class is matched against' do
39
+ subject {
40
+ module BaseModule; end
41
+
42
+ class TestClass; end
43
+
44
+ Typist::Func.new(:alpha) do
45
+ match(TestClass) { puts 'This should not happen!' }
46
+ end
47
+ }
48
+
49
+ it 'raises a MatchError' do
50
+ expect { subject.define!(BaseModule) }
51
+ .to raise_error(Typist::Error::MatchError)
52
+ end
53
+ end
54
+
55
+ context 'when only valid subclasses are matched against' do
56
+ subject {
57
+ module BaseModule; end
58
+
59
+ class Matches; include BaseModule; end
60
+ class DoesNotMatch; include BaseModule; end
61
+
62
+ Typist::Func.new(:alpha) do
63
+ match(Matches) { 'qt3.14' }
64
+ end
65
+ }
66
+
67
+ before { subject.define!(BaseModule) }
68
+
69
+ context 'when a subclass does not match against this function' do
70
+ it 'raises a PatternError' do
71
+ expect { DoesNotMatch.new.alpha }
72
+ .to raise_error(Typist::Error::PatternError)
73
+ end
74
+ end
75
+
76
+ context 'when a subclass does match against the function' do
77
+ it 'evaluates its match' do
78
+ Matches.new.alpha.should == 'qt3.14'
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Typist::Util do
4
+ subject { Typist::Util }
5
+
6
+ describe '#snakeify' do
7
+ let(:hash) {
8
+ {
9
+ 'ThisString' => 'this_string',
10
+ 'thatString' => 'that_string',
11
+ 'HeLlO' => 'he_ll_o'
12
+ }
13
+ }
14
+
15
+ it 'converts CamelCase Strings to snake_case' do
16
+ hash.each { |camel, snake| subject.snakeify(camel).should == snake }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Typist do
4
+ it { should be_a Module }
5
+
6
+ describe '#data' do
7
+ before do
8
+ extend Typist
9
+
10
+ data :Boolean do
11
+ constructor :True
12
+ constructor :False
13
+
14
+ func :to_i do
15
+ match(Boolean::False) { 0 }
16
+ match(Boolean::True) { 1 }
17
+ end
18
+ end
19
+ end
20
+
21
+ it 'defines a data type' do
22
+ Boolean.should be_a Module
23
+
24
+ Boolean.false.should be_a Boolean::False
25
+ Boolean.true.should be_a Boolean::True
26
+
27
+ Boolean.false.to_i.should == 0
28
+ Boolean.true.to_i.should == 1
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'rspec'
4
+ require 'typist'
5
+
6
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
7
+
8
+ RSpec.configure do |config|
9
+ config.mock_with :rspec
10
+ config.treat_symbols_as_metadata_keys_with_true_values = true
11
+ config.color_enabled = true
12
+ config.formatter = :documentation
13
+ config.tty = true
14
+ end
data/typist.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/typist/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Tom Hulihan']
6
+ gem.email = %w{hulihan.tom159@gmail.com}
7
+ gem.description = %q{Algebraic data types for Ruby}
8
+ gem.summary = %q{Algebraic data types for Ruby}
9
+ gem.homepage = 'https://github.com/nahiluhmot/typist'
10
+ gem.license = 'MIT'
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = 'typist'
15
+ gem.require_paths = %w{lib}
16
+ gem.version = Typist::VERSION
17
+ gem.add_development_dependency 'rake'
18
+ gem.add_development_dependency 'rspec'
19
+ gem.add_development_dependency 'cane'
20
+ gem.add_development_dependency 'pry'
21
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: typist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tom Hulihan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: cane
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Algebraic data types for Ruby
70
+ email:
71
+ - hulihan.tom159@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - README.md
80
+ - Rakefile
81
+ - lib/typist.rb
82
+ - lib/typist/constructor.rb
83
+ - lib/typist/data.rb
84
+ - lib/typist/error.rb
85
+ - lib/typist/func.rb
86
+ - lib/typist/util.rb
87
+ - lib/typist/version.rb
88
+ - spec/lib/typist/constructor_spec.rb
89
+ - spec/lib/typist/data_spec.rb
90
+ - spec/lib/typist/func_spec.rb
91
+ - spec/lib/typist/util_spec.rb
92
+ - spec/lib/typist_spec.rb
93
+ - spec/spec_helper.rb
94
+ - typist.gemspec
95
+ homepage: https://github.com/nahiluhmot/typist
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.2.0
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Algebraic data types for Ruby
119
+ test_files:
120
+ - spec/lib/typist/constructor_spec.rb
121
+ - spec/lib/typist/data_spec.rb
122
+ - spec/lib/typist/func_spec.rb
123
+ - spec/lib/typist/util_spec.rb
124
+ - spec/lib/typist_spec.rb
125
+ - spec/spec_helper.rb