typist 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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