algebrick 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c59b78e81ddad7a8982de954309dba01ccc26db9
4
- data.tar.gz: 94cbecbb1b1bd1f3ca682fa0707439b7afcba7fc
3
+ metadata.gz: 986e5746d10e9a2e2edf3c25da212fff33719dee
4
+ data.tar.gz: a711d19897aa1c4085948aa21cace8a86ede5ef6
5
5
  SHA512:
6
- metadata.gz: aeff2d9b02f3f947f0019c9c915f37194a1c02bc4d20eef4f7365ad22c836c8b4158b10cfc0686f66e9a640bb0cb1dff0cc39c253328ee043926f6dfe9dc851e
7
- data.tar.gz: d225e46f414574b28ff8719639d1ce193fe12e86935d27a9faef0bcaed2c3003ee2eebaf5eb336bdaf5f697d3f3ab8d24bd84df1e98c69d3f2d3161950b87453
6
+ metadata.gz: 5c0264da1e050dab04f2238905fab10b253762c68bcaa3c80103a6c4366efb236c003c3b8ce06cba03b0a0a7913f63662bf9246181237215881c99c77856d14a
7
+ data.tar.gz: 52d55de9dd00eebb7b6e38959cbf8bae0add19090ff04213a58a053f30389ef313669c41831848d5bf942f6a11274e4c1729f21dbd3b77256d1f4b2c02cac1dc
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ## Algebrick
2
2
 
3
- Algebraic types and pattern matching for Ruby.
3
+ Is a small gem providing algebraic types and pattern matching on them for Ruby.
4
4
 
5
- - Documentation: http://blog.pitr.ch/algebrick
6
- - Source: https://github.com/pitr-ch/algebrick
7
- - Blog: http://blog.pitr.ch/blog/categories/algebrick/
5
+ - Documentation: <http://blog.pitr.ch/algebrick>
6
+ - Source: <https://github.com/pitr-ch/algebrick>
7
+ - Blog: <http://blog.pitr.ch/blog/categories/algebrick/>
data/README_FULL.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Is a small gem providing algebraic types and pattern matching on them for Ruby.
4
4
 
5
- - Documentation: {http://blog.pitr.ch/algebrick}
6
- - Source: {https://github.com/pitr-ch/algebrick}
7
- - Blog: {http://blog.pitr.ch}
5
+ - Documentation: <http://blog.pitr.ch/algebrick>
6
+ - Source: <https://github.com/pitr-ch/algebrick>
7
+ - Blog: <http://blog.pitr.ch/blog/categories/algebrick/>
8
8
 
9
9
  ## Quick example with Maybe type
10
10
 
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.2
data/lib/algebrick.rb CHANGED
@@ -13,6 +13,10 @@ end
13
13
 
14
14
  module Algebrick
15
15
 
16
+ def self.version
17
+ @version ||= Gem::Version.new File.read(File.join(File.dirname(__FILE__), '..', 'VERSION'))
18
+ end
19
+
16
20
  module TypeCheck
17
21
  #def is_kind_of?(value, *types)
18
22
  # a_type_check :kind_of?, false, value, *types
@@ -22,9 +26,9 @@ module Algebrick
22
26
  a_type_check :kind_of?, true, value, *types
23
27
  end
24
28
 
25
- #def is_matching?(value, *types)
26
- # a_type_check :===, false, value, *types
27
- #end
29
+ def is_matching?(value, *types)
30
+ a_type_check :===, false, value, *types
31
+ end
28
32
 
29
33
  def is_matching!(value, *types)
30
34
  a_type_check :===, true, value, *types
@@ -43,8 +47,10 @@ module Algebrick
43
47
  raise ArgumentError
44
48
  end
45
49
  end
46
- raise TypeError, "value (#{value.class}) '#{value}' is not ##{which} any of #{types.join(', ')}" if bang && !ok
47
- value
50
+ bang && !ok and
51
+ raise TypeError,
52
+ "value (#{value.class}) '#{value}' is not ##{which} any of #{types.join(', ')}"
53
+ bang ? value : ok
48
54
  end
49
55
  end
50
56
 
@@ -83,7 +89,7 @@ module Algebrick
83
89
  cases.each do |matcher, block|
84
90
  return match_value matcher, block if matcher === value
85
91
  end
86
- raise "no match for #{value} by any of #{cases.map(&:first).join ', '}"
92
+ raise "no match for (#{value.class}) '#{value}' by any of #{cases.map(&:first).join ', '}"
87
93
  end
88
94
 
89
95
  private
@@ -307,6 +313,20 @@ module Algebrick
307
313
  self
308
314
  end
309
315
 
316
+ def add_field_method_accessor(field)
317
+ raise TypeError, 'no field names' unless @field_names
318
+ raise TypeError, "no field name #{field}" unless @field_names.include? field
319
+ define_method(field) { self[field] }
320
+ end
321
+
322
+ def add_field_method_accessors(*fields)
323
+ fields.each { |f| add_field_method_accessor f }
324
+ end
325
+
326
+ def add_all_field_method_accessors
327
+ add_field_method_accessors *@field_names
328
+ end
329
+
310
330
  protected
311
331
 
312
332
  def be_kind_of!(type)
@@ -336,7 +356,9 @@ module Algebrick
336
356
  if keys
337
357
  @field_names = keys
338
358
  keys.all? { |k| is_kind_of! k, Symbol }
339
- dict = @field_indexes = keys.each_with_index.inject({}) { |h, (k, i)| h.update k => i }
359
+ dict = @field_indexes =
360
+ Hash.new { |h, k| raise ArgumentError, "uknown field #{k.inspect}" }.
361
+ update keys.each_with_index.inject({}) { |h, (k, i)| h.update k => i }
340
362
  define_method(:[]) { |key| @fields[dict[key]] }
341
363
  end
342
364
 
@@ -551,6 +573,8 @@ module Algebrick
551
573
 
552
574
  alias_method :>>, :-
553
575
 
576
+ raise 'remove deprecation' if Algebrick.version >= Gem::Version.new('0.2')
577
+
554
578
  def +(block)
555
579
  warn 'a_matcher +-> {} is deprecated, it\'ll be removed in 0.2'
556
580
  self - block
@@ -678,7 +702,7 @@ module Algebrick
678
702
  end
679
703
  end
680
704
 
681
- class Not < Abstract # TODO
705
+ class Not < Abstract
682
706
  attr_reader :matcher
683
707
 
684
708
  def initialize(matcher)
@@ -1012,8 +1036,14 @@ module Algebrick
1012
1036
  end
1013
1037
  end
1014
1038
 
1015
- def type_def(&definition)
1016
- Environment.new(self, &definition).run
1039
+ def type_def(base = self, &definition)
1040
+ Environment.new(base, &definition).run
1017
1041
  end
1018
1042
  end
1043
+
1044
+ extend DSL
1045
+
1046
+ def self.type_def(base, &definition)
1047
+ super base, &definition
1048
+ end
1019
1049
  end
data/spec/algebrick.rb ADDED
@@ -0,0 +1,541 @@
1
+ require 'bundler/setup'
2
+
3
+ require 'minitest/spec'
4
+ #require 'minitest/autorun'
5
+ require 'turn/autorun'
6
+
7
+ require 'pp'
8
+ require_relative '../lib/algebrick'
9
+ require 'pry'
10
+
11
+ class Module
12
+ def const_missing const
13
+ raise "no constant #{const.inspect} in #{self}"
14
+ end
15
+ end
16
+
17
+ Turn.config do |c|
18
+ # use one of output formats:
19
+ # :outline - turn's original case/test outline mode [default]
20
+ # :progress - indicates progress with progress bar
21
+ # :dotted - test/unit's traditional dot-progress mode
22
+ # :pretty - new pretty reporter
23
+ # :marshal - dump output as YAML (normal run mode only)
24
+ # :cue - interactive testing
25
+ c.format = :outline
26
+ # turn on invoke/execute tracing, enable full backtrace
27
+ #c.trace = true
28
+ # use humanized test names (works only with :outline format)
29
+ c.natural = true
30
+ end
31
+
32
+
33
+ describe 'AlgebrickTest' do
34
+ i_suck_and_my_tests_are_order_dependent!
35
+
36
+ #type_def do
37
+ # maybe === none | some(Object)
38
+
39
+ # message === success | failure
40
+ # sucess === int(Integer) | str(String)
41
+ # failure === error | str_error(String)
42
+
43
+ #user = user(String, address) do
44
+ # def name
45
+ # fields[0]
46
+ # end
47
+ #
48
+ # def address
49
+ # fields[1]
50
+ # end
51
+ #end
52
+ #
53
+ #psc = psc(String) do
54
+ # REG = /\d{5}/
55
+ #
56
+ # def initialize(*fields)
57
+ # raise TypeError unless fields[0] =~ REG
58
+ # end
59
+ #
60
+ # def schema
61
+ # super << { pattern: REG.to_s }
62
+ # end
63
+ #end
64
+ #
65
+ ## street, num, city
66
+ #address = address(street(String), street_number(Integer), city(String), psc)
67
+ #
68
+ #message1 === user
69
+ #
70
+ #User['pepa',
71
+ # Adress[
72
+ # Street['Stavebni'],
73
+ # StreetNumber[5],
74
+ # City['Brno']]]
75
+ #
76
+ #{ user: ['pepa',
77
+ # { address: [{ street: 'Stavebni' },
78
+ # { street_number: 5 }] }] }
79
+
80
+ #sucess === int(Integer) | str(String)
81
+ #failure === error | str_error(String)
82
+ #message === success | failure
83
+
84
+
85
+ #list === empty | list_item(Integer, list)
86
+ #end
87
+
88
+ #Empty = Algebrick::Atom.new
89
+ #Leaf = Algebrick::Product.new(Integer)
90
+ #Tree = Algebrick::Variant.allocate
91
+ #Node = Algebrick::Product.new(Tree, Tree)
92
+ #Tree.send :initialize, Empty, Leaf, Node do
93
+ # def a
94
+ # :a
95
+ # end
96
+ #end
97
+ #List = Algebrick::ProductVariant.allocate
98
+ #List.send :initialize, [Integer, List], [Empty, List]
99
+
100
+ extend Algebrick::DSL
101
+
102
+ type_def do
103
+ tree === empty | leaf(Integer) | node(tree, tree)
104
+ tree do
105
+ def a
106
+ :a
107
+ end
108
+
109
+ def depth
110
+ case self
111
+ when Empty
112
+ 0
113
+ when Leaf
114
+ 1
115
+ when Node
116
+ left, right = *self
117
+ 1 + [left.depth, right.depth].max
118
+ end
119
+ end
120
+
121
+ def each(&block)
122
+ return to_enum :each unless block
123
+ case self
124
+ when Empty
125
+ when Leaf
126
+ block.call self.value
127
+ when Node
128
+ left, right = *self
129
+ left.each &block
130
+ right.each &block
131
+ end
132
+ end
133
+
134
+ def sum
135
+ each.inject(0) { |sum, v| sum + v }
136
+ end
137
+ end
138
+
139
+ list === empty | list(Integer, list)
140
+ end
141
+
142
+ Empty = self::Empty
143
+ Node = self::Node
144
+ Leaf = self::Leaf
145
+ Tree = self::Tree
146
+ List = self::List
147
+
148
+ describe 'type definition' do
149
+ module Asd
150
+ Algebrick.type_def self do
151
+ b === c | d
152
+ end
153
+ end
154
+
155
+ it 'asd' do
156
+ assert Asd::B
157
+ end
158
+ end
159
+
160
+ describe 'type.to_s' do
161
+ it { Empty.to_s.must_equal 'Empty' }
162
+ it { Node.to_s.must_equal 'Node(Tree, Tree)' }
163
+ it { Leaf.to_s.must_equal 'Leaf(Integer)' }
164
+ it { Tree.to_s.must_equal 'Tree(Empty | Leaf | Node)' }
165
+ it { List.to_s.must_equal 'List(Empty | List(Integer, List))' }
166
+ end
167
+
168
+ describe 'atom' do
169
+ it { Empty.must_be_kind_of Algebrick::Type }
170
+ it { Empty.must_be_kind_of Algebrick::Value }
171
+ it { assert Empty.kind_of? Empty }
172
+
173
+ it { assert Empty == Empty }
174
+ it { assert Empty === Empty }
175
+ it { eval(Empty.to_s).must_equal Empty }
176
+ it { eval(Empty.inspect).must_equal Empty }
177
+
178
+ it { Empty.from_hash(Empty.to_hash).must_equal Empty }
179
+ end
180
+
181
+ describe 'product' do
182
+ it { Leaf[1].must_be_kind_of Algebrick::Value }
183
+ it { Leaf.must_be_kind_of Algebrick::Type }
184
+ it { Leaf[1].wont_be_kind_of Algebrick::Type }
185
+ it { Leaf.wont_be_kind_of Algebrick::Value }
186
+
187
+ it { assert Leaf[1] == Leaf[1] }
188
+ it { assert Leaf[1] != Leaf[0] }
189
+ it { assert Leaf === Leaf[1] }
190
+ it { assert Leaf[1].kind_of? Leaf }
191
+ it { eval(Leaf[1].to_s).must_equal Leaf[1] }
192
+ it { eval(Leaf[1].inspect).must_equal Leaf[1] }
193
+ it { eval(Node[Leaf[1], Empty].to_s).must_equal Node[Leaf[1], Empty] }
194
+ it { eval(Node[Leaf[1], Empty].inspect).must_equal Node[Leaf[1], Empty] }
195
+
196
+ it 'field assign' do
197
+ value = Leaf[1].value
198
+ value.must_equal 1
199
+
200
+ left, right = *Node[Empty, Leaf[1]]
201
+ left.must_equal Empty
202
+ right.must_equal Leaf[1]
203
+
204
+ lambda { Node[Empty, Empty].value }.must_raise NoMethodError
205
+ end
206
+
207
+ it { lambda { Leaf['a'] }.must_raise TypeError }
208
+ it { lambda { Leaf[nil] }.must_raise TypeError }
209
+ it { lambda { Node['a'] }.must_raise TypeError }
210
+ it { lambda { Node[Empty, nil] }.must_raise TypeError }
211
+
212
+ describe 'named field' do
213
+ type_def { named(a: Integer, b: Object) }
214
+ Named = self::Named
215
+ Named.add_all_field_method_accessors
216
+ it { -> { Named[:a, 1] }.must_raise TypeError }
217
+ it { Named[1, :a][:a].must_equal 1 }
218
+ it { Named[1, :a][:b].must_equal :a }
219
+ it { Named[a: 1, b: :a][:a].must_equal 1 }
220
+ it { Named[b: :a, a: 1][:a].must_equal 1 }
221
+ it { Named[a: 1, b: :a][:b].must_equal :a }
222
+ it { Named[a: 1, b: 2].to_s.must_equal 'Named[a: 1, b: 2]' }
223
+ it { Named[a: 1, b: 2].a.must_equal 1 }
224
+ it { Named[a: 1, b: 2].b.must_equal 2 }
225
+ end
226
+
227
+ it { Leaf.from_hash(Leaf[1].to_hash).must_equal Leaf[1] }
228
+ it { Named.from_hash(Named[1, :a].to_hash).must_equal Named[1, :a] }
229
+ it { Named[1, Leaf[1]].to_hash.must_equal 'Named' => { a: 1, b: { 'Leaf' => [1] } } }
230
+ it { Named.from_hash(Named[1, Leaf[1]].to_hash).must_equal Named[1, Leaf[1]] }
231
+
232
+ end
233
+
234
+ describe 'variant' do
235
+ it { Tree.must_be_kind_of Algebrick::Type }
236
+ it { Empty.must_be_kind_of Tree }
237
+ it { Empty.a.must_equal :a }
238
+ it { Leaf[1].must_be_kind_of Tree }
239
+ it { Leaf[1].a.must_equal :a }
240
+ it { Node[Empty, Empty].must_be_kind_of Tree }
241
+ #it { assert Empty.kind_of? List }
242
+
243
+ it { assert Tree === Empty }
244
+ it { assert Tree === Leaf[1] }
245
+
246
+ describe 'inherit behavior deep' do
247
+ type_def do
248
+ a === a1 | a2
249
+ a1 === b1 | b2
250
+ a do
251
+ def a
252
+ :a
253
+ end
254
+ end
255
+ end
256
+
257
+ it { self.class::B1.a.must_equal :a }
258
+ end
259
+
260
+ describe 'a klass as a variant' do
261
+ MaybeString = Algebrick::Variant.new Empty, String
262
+ it { 'a'.must_be_kind_of MaybeString }
263
+ end
264
+ end
265
+
266
+ describe 'product_variant' do
267
+ it { List[1, Empty].must_be_kind_of Algebrick::Value }
268
+ it { List.must_be_kind_of Algebrick::Type }
269
+
270
+ it { List[1, Empty].must_be_kind_of List }
271
+ it { List[1, List[1, Empty]].must_be_kind_of List }
272
+ it { Empty.must_be_kind_of List }
273
+
274
+ it { assert List[1, Empty] == List[1, Empty] }
275
+ it { assert List[1, Empty] != List[2, Empty] }
276
+ it { assert List === List[1, Empty] }
277
+ it { assert List === Empty }
278
+ it { assert List[1, Empty].kind_of? List }
279
+ end
280
+
281
+ describe '#depth' do
282
+ it do
283
+ tree = Node[Node[Empty, Leaf[1]], Leaf[1]]
284
+ tree.depth.must_equal 3
285
+ end
286
+ it do
287
+ tree = Node[Empty, Leaf[1]]
288
+ tree.depth.must_equal 2
289
+ end
290
+ it do
291
+ tree = Empty
292
+ tree.depth.must_equal 0
293
+ end
294
+ end
295
+
296
+ describe '#sum' do
297
+ it do
298
+ tree = Node[Node[Empty, Leaf[1]], Leaf[1]]
299
+ tree.sum.must_equal 2
300
+ end
301
+ end
302
+
303
+ describe 'maybe' do
304
+ type_def do
305
+ maybe === none | some(Object)
306
+ maybe do
307
+ def maybe(&block)
308
+ case self
309
+ when None
310
+ when Some
311
+ block.call self.value
312
+ end
313
+ end
314
+ end
315
+ end
316
+
317
+ None = self::None
318
+ Some = self::Some
319
+
320
+ it { refute None.maybe { true } }
321
+ it { assert Some[nil].maybe { true } }
322
+ end
323
+
324
+ extend Algebrick::Matching
325
+ include Algebrick::Matching
326
+
327
+ describe 'matchers' do
328
+ it 'assigns' do
329
+ m = ~Empty
330
+ m === 2
331
+ m.assigns.must_equal [nil]
332
+ m === Empty
333
+ m.assigns.must_equal [Empty]
334
+
335
+ m = ~String.to_m
336
+ m === 2
337
+ m.assigns.must_equal [nil]
338
+ m === 'a'
339
+ m.assigns.must_equal %w(a)
340
+
341
+ m = ~Leaf.(~any)
342
+ m === Leaf[5]
343
+ m.assigns.must_equal [Leaf[5], 5]
344
+ m === Leaf[3]
345
+ m.assigns.must_equal [Leaf[3], 3]
346
+ end
347
+
348
+ it 'assigns in case' do
349
+ case Leaf[5]
350
+ when m = ~Leaf.(~any)
351
+ m.assigns.must_equal [Leaf[5], 5]
352
+ m.assigns do |leaf, value|
353
+ leaf.must_equal Leaf[5]
354
+ value.must_equal 5
355
+ end
356
+ else
357
+ raise
358
+ end
359
+ end
360
+
361
+ describe 'match' do
362
+ it 'returns value from executed block' do
363
+ Algebrick.match(Empty, Empty.to_m.case { 1 }).must_equal 1
364
+ end
365
+
366
+ it 'passes assigned values' do
367
+ v = Algebrick.match Leaf[5],
368
+ Leaf.(~any).case { |value| value }
369
+ v.must_equal 5
370
+
371
+ v = Algebrick.match Leaf[5],
372
+ Leaf.(~any) => -> value { value }
373
+ v.must_equal 5
374
+ end
375
+
376
+ it 'raises when no match' do
377
+ -> { Algebrick.match Empty,
378
+ Leaf.(any).case {} }.must_raise RuntimeError
379
+ end
380
+
381
+ it 'does not pass any values when no matcher' do
382
+ Algebrick.match(Empty, Empty => -> *a { a }).must_equal []
383
+ end
384
+ end
385
+
386
+ describe '#to_s' do
387
+ [Empty.to_m,
388
+ # leaf(Object)
389
+ ~Leaf.(Integer),
390
+ ~Empty.to_m,
391
+ any,
392
+ ~any,
393
+ Leaf.(any),
394
+ ~Leaf.(any),
395
+ Node.(Leaf.(any), any),
396
+ ~Node.(Leaf.(any), any),
397
+ ~Leaf.(1) | Leaf.(~any),
398
+ ~Leaf.(1) & Leaf.(~any)
399
+ ].each do |matcher|
400
+ it matcher.to_s do
401
+ eval(matcher.to_s).must_equal matcher
402
+ end
403
+ end
404
+ end
405
+
406
+ { Empty.to_m => Empty,
407
+ any => Empty,
408
+ any => Leaf[1],
409
+
410
+ Empty => Empty,
411
+ Empty.to_m => Empty,
412
+
413
+ Leaf => Leaf[1],
414
+ Leaf.(any) => Leaf[5],
415
+ Leaf.(~any) => Leaf[5],
416
+
417
+ Node => Node[Empty, Empty],
418
+ Node.(any, any) => Node[Leaf[1], Empty],
419
+ Node.(Empty, any) => Node[Empty, Leaf[1]],
420
+ Node.(Leaf.(any), any) => Node[Leaf[1], Empty],
421
+ Node.(Leaf.(any), any) => Node[Leaf[1], Empty],
422
+
423
+ Tree.to_m => Node[Leaf[1], Empty],
424
+ Tree.to_m => Node[Leaf[1], Empty],
425
+ Node => Node[Leaf[1], Empty],
426
+
427
+ Tree & Leaf.(_) => Leaf[1],
428
+ Empty | Leaf.(_) => Leaf[1],
429
+ Empty | Leaf.(_) => Empty,
430
+ !Empty & Leaf.(_) => Leaf[1],
431
+ Empty & !Leaf.(_) => Empty,
432
+
433
+ Array.() => [],
434
+ Array.(1) => [1],
435
+ Array.(Empty, Leaf.(-> v { v > 0 })) => [Empty, Leaf[1]],
436
+ Array.(TrueClass) => [true],
437
+
438
+ }.each do |matcher, value|
439
+ it "#{matcher} === #{value}" do
440
+ assert matcher === value
441
+ end
442
+ end
443
+ end
444
+
445
+ it {
446
+ assert List.to_m === Empty
447
+ assert List === Empty
448
+ assert List.to_m === List[1, Empty]
449
+ assert List === List[1, Empty]
450
+ assert List.(1, _) === List[1, Empty]
451
+ refute List.(_, _) === Empty
452
+ }
453
+
454
+ describe 'and-or matching' do
455
+ it do
456
+ m = ~Leaf.(1) | ~Leaf.(~any)
457
+ assert m === Leaf[1]
458
+ m.assigns.must_equal [Leaf[1], nil, nil]
459
+ end
460
+ it do
461
+ m = ~Leaf.(1) | ~Leaf.(~any)
462
+ assert m === Leaf[2]
463
+ m.assigns.must_equal [nil, Leaf[2], 2]
464
+ end
465
+ it do
466
+ m = ~Leaf.(->(v) { v > 1 }) & Leaf.(~any)
467
+ assert m === Leaf[2]
468
+ m.assigns.must_equal [Leaf[2], 2]
469
+ end
470
+
471
+ end
472
+
473
+ describe 'equality' do
474
+ data = (0..1).map do
475
+ [Empty,
476
+ Leaf[1],
477
+ Node[Empty, Leaf[1]],
478
+ Node[Node[Empty, Leaf[1]], Leaf[1]]]
479
+ end
480
+ data[0].zip(data[1]).each do |tree1, tree2|
481
+ it "equals #{tree1}" do
482
+ refute tree1.object_id == tree2.object_id, [tree1.object_id, tree2.object_id] unless tree1 == Empty
483
+ assert tree1 == tree2
484
+ end
485
+ end
486
+ end
487
+
488
+ describe 'list' do
489
+ it { List.(any, any) === List[1, Empty] }
490
+ it { List.(any, List) === List[1, Empty] }
491
+ end
492
+
493
+ describe 'binary tree' do
494
+ type_def { b_tree === tip | b_node(Object, b_tree, b_tree) }
495
+ end
496
+
497
+ end
498
+
499
+
500
+ #require 'benchmark'
501
+ #
502
+ #include Algebrick
503
+ #
504
+ #class None < Atom
505
+ #end
506
+ #
507
+ #class Some < Product
508
+ # fields Object
509
+ #end
510
+ #
511
+ #Maybe = Variant.new do
512
+ # variants None, Some
513
+ #end
514
+ #count = 1000_000
515
+ #
516
+ #Benchmark.bmbm(10) do |b|
517
+ # b.report('nil') do
518
+ # count.times do
519
+ # v = [Object.new, nil].sample
520
+ # case v
521
+ # when Object
522
+ # true
523
+ # when nil
524
+ # false
525
+ # end
526
+ # end
527
+ # end
528
+ # b.report('Maybe') do
529
+ # count.times do
530
+ # v = [Some[Object.new], None].sample
531
+ # case v
532
+ # when Some
533
+ # true
534
+ # when Maybe
535
+ # false
536
+ # end
537
+ # end
538
+ # end
539
+ #
540
+ #
541
+ #end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algebrick
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Petr Chalupa
@@ -104,9 +104,11 @@ extra_rdoc_files:
104
104
  - README_FULL.md
105
105
  files:
106
106
  - lib/algebrick.rb
107
+ - VERSION
107
108
  - MIT-LICENSE
108
109
  - README.md
109
110
  - README_FULL.md
111
+ - spec/algebrick.rb
110
112
  homepage: https://github.com/pitr-ch/algebrick
111
113
  licenses:
112
114
  - MIT
@@ -131,5 +133,6 @@ rubygems_version: 2.0.0
131
133
  signing_key:
132
134
  specification_version: 4
133
135
  summary: Algebraic types and pattern matching for Ruby
134
- test_files: []
136
+ test_files:
137
+ - spec/algebrick.rb
135
138
  has_rdoc: