haskell 0.0.1 → 0.0.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 +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
|