haskell 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/README.md +51 -4
- data/a +11 -0
- data/bin/haskell +0 -0
- data/lib/haskell.rb +41 -3
- data/lib/haskell/type_list.rb +32 -0
- data/lib/haskell/version.rb +1 -1
- data/test/test_haskell.rb +95 -4
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b85cd42c60a8fd8905a866a3ef595379fc061422
|
4
|
+
data.tar.gz: 95a13b1c977a43d4bcfaa1c3c34ba4f35b83994f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bb0e886c7bce3e0ad68e20c1269df8e5874ec6104d16ff570598a40d03cabe098a60deec053f4ba6bb0e6081e20b64cf8ab7622fc1a4c41e34989fb0f3446ad
|
7
|
+
data.tar.gz: 3626c9b3b1daa0e0a57b211308d3a21275729c4702c0978e14063015f3720a31ab825e1fe38fcb555fec47ce24d39ad988fc11f7d73186f4723c4a24cc79f22b
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,37 @@
|
|
1
|
-
#
|
1
|
+
# Ruby with Type.
|
2
2
|
|
3
|
-
|
3
|
+
```rb
|
4
|
+
|
5
|
+
require 'haskell'
|
6
|
+
|
7
|
+
# Ruby 2.1.0+
|
8
|
+
class MyClass
|
9
|
+
type Numeric >= Numeric >= Numeric, def sum(x, y)
|
10
|
+
x + y
|
11
|
+
end
|
12
|
+
|
13
|
+
type Numeric >= Numeric >= Numeric, def wrong_sum(x, y)
|
14
|
+
'string'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
MyClass.new.sum(1, 2)
|
19
|
+
#=> 3
|
20
|
+
|
21
|
+
MyClass.new.sum(1, 'string')
|
22
|
+
#=> ArgumentError: Wrong type of argument, type of "str" should be Numeric
|
23
|
+
|
24
|
+
MyClass.new.wrong_sum(1, 2)
|
25
|
+
#=> TypeError: Expected wrong_sum to return Numeric but got "str" instead
|
26
|
+
|
27
|
+
# Ruby 1.8.0+
|
28
|
+
class MyClass
|
29
|
+
def sum(x, y)
|
30
|
+
x + y
|
31
|
+
end
|
32
|
+
type Numeric >= Numeric >= Numeric, :sum
|
33
|
+
end
|
34
|
+
```
|
4
35
|
|
5
36
|
## Installation
|
6
37
|
|
@@ -18,9 +49,21 @@ Or install it yourself as:
|
|
18
49
|
|
19
50
|
$ gem install haskell
|
20
51
|
|
21
|
-
##
|
52
|
+
## More example
|
53
|
+
```ruby
|
54
|
+
class People
|
55
|
+
type People >= Any, def marry(people)
|
56
|
+
# Your Ruby code as usual
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
People.new.marry(People.new)
|
61
|
+
#=> no error
|
22
62
|
|
23
|
-
|
63
|
+
People.new.marry('non people')
|
64
|
+
#=> ArgumentError: Wrong type of argument, type of "non people" should be People
|
65
|
+
|
66
|
+
```
|
24
67
|
|
25
68
|
## Contributing
|
26
69
|
|
@@ -29,3 +72,7 @@ TODO: Write usage instructions here
|
|
29
72
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
30
73
|
4. Push to the branch (`git push origin my-new-feature`)
|
31
74
|
5. Create a new Pull Request
|
75
|
+
|
76
|
+
|
77
|
+
## Credits
|
78
|
+
[@chancancode](https://github.com/chancancode) first brought this to my attention.
|
data/a
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
def test_any
|
2
|
+
assert_wrong_arg @symbo >= @symbo, [@array ], @numeric
|
3
|
+
assert_wrong_arg @symbo >= @symbo, [@string], @numeric
|
4
|
+
assert_wrong_arg @symbo >= @symbo, [@hash ], @numeric
|
5
|
+
assert_wrong_arg @symbo >= @symbo, [@symbol], @numeric
|
6
|
+
|
7
|
+
assert_wrong_arg @symbo >= @symbo >= @symbo, [@numeric, @array ], @numeric
|
8
|
+
assert_wrong_arg @symbo >= @symbo >= @symbo, [@numeric, @string], @numeric
|
9
|
+
assert_wrong_arg @symbo >= @symbo >= @symbo, [@numeric, @hash ], @numeric
|
10
|
+
assert_wrong_arg @symbo >= @symbo >= @symbo, [@numeric, @symbol], @numeric
|
11
|
+
en
|
data/bin/haskell
CHANGED
File without changes
|
data/lib/haskell.rb
CHANGED
@@ -1,6 +1,44 @@
|
|
1
|
-
require
|
2
|
-
require "haskell/haskell"
|
1
|
+
require 'haskell/type_list'
|
3
2
|
|
4
3
|
module Haskell
|
5
|
-
|
4
|
+
class << self
|
5
|
+
def assert_arg_type(meth, args, klasses)
|
6
|
+
|
7
|
+
args.each_with_index do |arg, i|
|
8
|
+
if wrong_type?(arg, klasses[i])
|
9
|
+
raise ArgumentError, "Wrong type of argument, type of #{arg.inspect} should be #{klasses[i]}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def assert_rtn_type(meth, rtn, klass)
|
15
|
+
if wrong_type?(rtn, klass)
|
16
|
+
raise TypeError, "Expected #{meth} to return #{klass} but got #{rtn.inspect} instead"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def wrong_type?(obj, klass)
|
21
|
+
!(obj.is_a?(klass) || klass == Any)
|
22
|
+
end
|
23
|
+
end
|
6
24
|
end
|
25
|
+
|
26
|
+
class Module
|
27
|
+
private
|
28
|
+
def __haskell__
|
29
|
+
prepend (@__haskell__ = Module.new) unless @__haskell__
|
30
|
+
@__haskell__
|
31
|
+
end
|
32
|
+
|
33
|
+
def type(type_list, meth)
|
34
|
+
__haskell__.send(:define_method, meth) do |*args, &block|
|
35
|
+
::Haskell.assert_arg_type(meth, args, type_list.args)
|
36
|
+
rtn = super(*args, &block)
|
37
|
+
::Haskell.assert_rtn_type(meth, rtn, type_list.rtn)
|
38
|
+
rtn
|
39
|
+
end
|
40
|
+
self
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Any; end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# '>=' is left-associative ...
|
2
|
+
# List like LISP or Hash may be better.
|
3
|
+
class TypeList
|
4
|
+
attr_accessor :list
|
5
|
+
|
6
|
+
def initialize(l, r)
|
7
|
+
@list = [l, r]
|
8
|
+
end
|
9
|
+
|
10
|
+
def >=(r)
|
11
|
+
@list << r
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def args
|
16
|
+
@list[0..-2]
|
17
|
+
end
|
18
|
+
|
19
|
+
def rtn
|
20
|
+
@list.last
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
@list.map(&:to_s).join(' -> ')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Module
|
29
|
+
def >=(r)
|
30
|
+
TypeList.new(self, r)
|
31
|
+
end
|
32
|
+
end
|
data/lib/haskell/version.rb
CHANGED
data/test/test_haskell.rb
CHANGED
@@ -1,11 +1,102 @@
|
|
1
1
|
require 'minitest_helper'
|
2
2
|
|
3
3
|
class TestHaskell < MiniTest::Unit::TestCase
|
4
|
-
def
|
5
|
-
|
4
|
+
def setup
|
5
|
+
@string = 'str'
|
6
|
+
@numeric = 1
|
7
|
+
@symbol = :test
|
8
|
+
@array = [1, 2, 3]
|
9
|
+
@hash = { test: :hash }
|
6
10
|
end
|
7
11
|
|
8
|
-
def
|
9
|
-
|
12
|
+
def test_type_list
|
13
|
+
assert_equal_to_s "Numeric -> Numeric", Numeric >= Numeric
|
14
|
+
assert_equal_to_s "Numeric -> Numeric -> Array", Numeric >= Numeric >= Array
|
15
|
+
assert_equal_to_s "Hash -> Symbol -> Numeric -> Array -> String", Hash >= Symbol >= Numeric >= Array >= String
|
10
16
|
end
|
17
|
+
|
18
|
+
def test_correct_type
|
19
|
+
assert_correct_type Numeric >= Numeric, [@numeric], @numeric
|
20
|
+
assert_correct_type Numeric >= Array, [@numeric], @array
|
21
|
+
assert_correct_type Numeric >= String, [@numeric], @string
|
22
|
+
assert_correct_type Numeric >= Hash, [@numeric], @hash
|
23
|
+
assert_correct_type Numeric >= Symbol, [@numeric], @symbol
|
24
|
+
|
25
|
+
assert_correct_type Numeric >= Numeric >= Numeric, [@numeric, @numeric], @numeric
|
26
|
+
assert_correct_type Numeric >= Array >= Array, [@numeric, @array ], @array
|
27
|
+
assert_correct_type Numeric >= String >= String, [@numeric, @string ], @string
|
28
|
+
assert_correct_type Numeric >= Hash >= Hash, [@numeric, @hash ], @hash
|
29
|
+
assert_correct_type Numeric >= Symbol >= Symbol, [@numeric, @symbol ], @symbol
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_wrong_return_type
|
33
|
+
assert_wrong_rtn Numeric >= Numeric, [@numeric], @array
|
34
|
+
assert_wrong_rtn Numeric >= Numeric, [@numeric], @string
|
35
|
+
assert_wrong_rtn Numeric >= Numeric, [@numeric], @hash
|
36
|
+
assert_wrong_rtn Numeric >= Numeric, [@numeric], @symbol
|
37
|
+
|
38
|
+
assert_wrong_rtn Numeric >= Numeric >= Numeric, [@numeric, @numeric], @array
|
39
|
+
assert_wrong_rtn Numeric >= Numeric >= Numeric, [@numeric, @numeric], @string
|
40
|
+
assert_wrong_rtn Numeric >= Numeric >= Numeric, [@numeric, @numeric], @hash
|
41
|
+
assert_wrong_rtn Numeric >= Numeric >= Numeric, [@numeric, @numeric], @symbol
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_wrong_args_type
|
45
|
+
assert_wrong_arg Numeric >= Numeric, [@array ], @numeric
|
46
|
+
assert_wrong_arg Numeric >= Numeric, [@string], @numeric
|
47
|
+
assert_wrong_arg Numeric >= Numeric, [@hash ], @numeric
|
48
|
+
assert_wrong_arg Numeric >= Numeric, [@symbol], @numeric
|
49
|
+
|
50
|
+
assert_wrong_arg Numeric >= Numeric >= Numeric, [@numeric, @array ], @numeric
|
51
|
+
assert_wrong_arg Numeric >= Numeric >= Numeric, [@numeric, @string], @numeric
|
52
|
+
assert_wrong_arg Numeric >= Numeric >= Numeric, [@numeric, @hash ], @numeric
|
53
|
+
assert_wrong_arg Numeric >= Numeric >= Numeric, [@numeric, @symbol], @numeric
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_any
|
57
|
+
assert_correct_type Any >= Any, [@array ], @numeric
|
58
|
+
assert_correct_type Any >= Any, [@string], @numeric
|
59
|
+
assert_correct_type Any >= Any, [@hash ], @numeric
|
60
|
+
assert_correct_type Any >= Any, [@symbol], @numeric
|
61
|
+
|
62
|
+
assert_correct_type Any >= Any >= Any, [@numeric, @array ], @numeric
|
63
|
+
assert_correct_type Any >= Any >= Any, [@numeric, @string], @numeric
|
64
|
+
assert_correct_type Any >= Any >= Any, [@numeric, @hash ], @numeric
|
65
|
+
assert_correct_type Any >= Any >= Any, [@numeric, @symbol], @numeric
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def assert_equal_to_s(str, val)
|
70
|
+
assert_equal str, val.to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
def assert_correct_type(type_list, args, val)
|
74
|
+
assert_equal val, define_test_method(type_list, args, val).call(*args)
|
75
|
+
end
|
76
|
+
|
77
|
+
def assert_wrong_arg(type_list, args, val)
|
78
|
+
assert_raises(ArgumentError) { define_test_method(type_list, args, val).call(*args) }
|
79
|
+
end
|
80
|
+
|
81
|
+
def assert_wrong_rtn(type_list, args, val)
|
82
|
+
assert_raises(TypeError) { define_test_method(type_list, args, val).call(*args) }
|
83
|
+
end
|
84
|
+
|
85
|
+
def define_test_method(type_list, args, val)
|
86
|
+
klass = Class.new.class_eval <<-RUBY_CODE
|
87
|
+
type #{obj_literal(type_list)}, def call(#{arg_literal(args.count)})
|
88
|
+
#{obj_literal(val)}
|
89
|
+
end
|
90
|
+
RUBY_CODE
|
91
|
+
|
92
|
+
klass.new
|
93
|
+
end
|
94
|
+
|
95
|
+
def obj_literal(obj)
|
96
|
+
"ObjectSpace._id2ref(#{obj.__id__})"
|
97
|
+
end
|
98
|
+
|
99
|
+
def arg_literal(count)
|
100
|
+
('a'..'z').to_a[0..count-1].join(',')
|
101
|
+
end
|
11
102
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haskell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- gogotanaka
|
@@ -81,12 +81,14 @@ files:
|
|
81
81
|
- LICENSE.txt
|
82
82
|
- README.md
|
83
83
|
- Rakefile
|
84
|
+
- a
|
84
85
|
- bin/haskell
|
85
86
|
- ext/haskell/extconf.rb
|
86
87
|
- ext/haskell/haskell.c
|
87
88
|
- ext/haskell/haskell.h
|
88
89
|
- haskell.gemspec
|
89
90
|
- lib/haskell.rb
|
91
|
+
- lib/haskell/type_list.rb
|
90
92
|
- lib/haskell/version.rb
|
91
93
|
- test/minitest_helper.rb
|
92
94
|
- test/test_haskell.rb
|