monadt 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/monadt/adt.rb +33 -0
- data/lib/monadt/either.rb +35 -0
- data/lib/monadt/list.rb +17 -0
- data/lib/monadt/maybe.rb +51 -0
- data/lib/monadt/monad.rb +43 -0
- data/lib/monadt/reader.rb +16 -0
- data/lib/monadt/reader_state_either.rb +24 -0
- data/lib/monadt/state.rb +16 -0
- data/lib/monadt.rb +49 -0
- metadata +53 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c19e86f991142006e0e23f98ec59c2a9780db485
|
4
|
+
data.tar.gz: 52cc959d8eeb05fa7d617d51278ec9b2aed00467
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a06ffff7277f97c3a16652bbb45ed0d0c13a9ad382772a58d372dbdf9b93e2ae45ce9eafdca7612ed29dffc9a5c1513a4be98d2cae09fb128450e2f5142f91d4
|
7
|
+
data.tar.gz: a61dab72be3127c89f11d33ad49af0094838073554719fd2f10de78a6408120302c9818c5843ec71b94c379f43d0348e962dbd5a80591cd545b3e6d6bea23b93
|
data/lib/monadt/adt.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
AdtPattern = Struct.new :klass, :lambda
|
2
|
+
|
3
|
+
def data(*fields)
|
4
|
+
base = if fields.size > 0
|
5
|
+
Struct.new(*fields)
|
6
|
+
else
|
7
|
+
Object
|
8
|
+
end
|
9
|
+
Class.new(base)
|
10
|
+
end
|
11
|
+
|
12
|
+
Default = data
|
13
|
+
|
14
|
+
module Adt
|
15
|
+
def match(o, *cases)
|
16
|
+
m = cases.find do |tpl|
|
17
|
+
tpl.klass == o.class || tpl.klass == Default
|
18
|
+
end
|
19
|
+
params =
|
20
|
+
if m.lambda.arity > 0
|
21
|
+
o.values.take(m.lambda.arity)
|
22
|
+
else
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
m.lambda.call(*params)
|
26
|
+
end
|
27
|
+
|
28
|
+
def with(klass, prc=nil, &blk)
|
29
|
+
AdtPattern.new klass, prc || blk
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'monadt/adt'
|
2
|
+
|
3
|
+
module Monadt
|
4
|
+
module Either
|
5
|
+
Left = data :left
|
6
|
+
Right = data :right
|
7
|
+
end
|
8
|
+
class Either::Left
|
9
|
+
def is_left?() true end
|
10
|
+
def is_right?() false end
|
11
|
+
def to_s() "Left(#{left})" end
|
12
|
+
end
|
13
|
+
class Either::Right
|
14
|
+
def is_left?() false end
|
15
|
+
def is_right?() true end
|
16
|
+
def to_s() "Right(#{right})" end
|
17
|
+
end
|
18
|
+
|
19
|
+
class EitherM
|
20
|
+
class << self
|
21
|
+
include Adt
|
22
|
+
|
23
|
+
def bind(m, &blk)
|
24
|
+
match(m,
|
25
|
+
with(Either::Left) { |v| m },
|
26
|
+
with(Either::Right) { |v| blk.call(v) })
|
27
|
+
end
|
28
|
+
|
29
|
+
def return(a)
|
30
|
+
Either::Right.new a
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
data/lib/monadt/list.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'maybe'
|
2
|
+
require_relative 'either'
|
3
|
+
require_relative 'state'
|
4
|
+
require_relative 'reader_state_either'
|
5
|
+
|
6
|
+
class ListM
|
7
|
+
class << self
|
8
|
+
def bind(m, &blk)
|
9
|
+
m.flat_map(&blk)
|
10
|
+
end
|
11
|
+
|
12
|
+
def return(a)
|
13
|
+
[a]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
data/lib/monadt/maybe.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'monadt/adt'
|
2
|
+
|
3
|
+
module Monadt
|
4
|
+
module Maybe
|
5
|
+
Just = data :value
|
6
|
+
Nothing = data
|
7
|
+
end
|
8
|
+
|
9
|
+
class Maybe::Just
|
10
|
+
def is_nothing?() false end
|
11
|
+
def to_s() "Just #{value}" end
|
12
|
+
end
|
13
|
+
class Maybe::Nothing
|
14
|
+
def is_nothing?() true end
|
15
|
+
def to_s() "Nothing" end
|
16
|
+
end
|
17
|
+
|
18
|
+
class MaybeM
|
19
|
+
class << self
|
20
|
+
include Adt
|
21
|
+
|
22
|
+
def bind(m, &blk)
|
23
|
+
match(m,
|
24
|
+
with(Maybe::Just) { |v| blk.call(v) },
|
25
|
+
with(Maybe::Nothing) { m })
|
26
|
+
end
|
27
|
+
|
28
|
+
def return(a)
|
29
|
+
Maybe::Just.new a
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# like Maybe but nil / not-nill
|
35
|
+
class PresentM
|
36
|
+
class << self
|
37
|
+
def bind(m, &blk)
|
38
|
+
if m.nil?
|
39
|
+
nil
|
40
|
+
else
|
41
|
+
blk.call(m)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def return(a)
|
46
|
+
a
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
data/lib/monadt/monad.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Monadt
|
2
|
+
module Internal
|
3
|
+
class MonadObj
|
4
|
+
def initialize(klass, yielder)
|
5
|
+
@yielder = yielder
|
6
|
+
@klass = klass
|
7
|
+
end
|
8
|
+
|
9
|
+
def return(val)
|
10
|
+
@klass.return val
|
11
|
+
end
|
12
|
+
|
13
|
+
def bind(val)
|
14
|
+
@yielder.yield val
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Monad
|
20
|
+
class << self
|
21
|
+
def do_m(klass, &blk)
|
22
|
+
e = Enumerator.new do |y|
|
23
|
+
m_obj = Internal::MonadObj.new klass, y
|
24
|
+
blk.call(m_obj)
|
25
|
+
end
|
26
|
+
do_m_recur(klass, e)
|
27
|
+
end
|
28
|
+
|
29
|
+
def do_m_recur(klass, e)
|
30
|
+
begin
|
31
|
+
ma = e.next
|
32
|
+
rescue StopIteration => ex
|
33
|
+
return ex.result
|
34
|
+
end
|
35
|
+
klass.bind(ma) do |a|
|
36
|
+
e.feed a
|
37
|
+
do_m_recur(klass, e)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'monadt/adt'
|
2
|
+
|
3
|
+
module Monadt
|
4
|
+
class ReaderStateEitherM
|
5
|
+
class << self
|
6
|
+
include Adt
|
7
|
+
|
8
|
+
def bind(m, &blk)
|
9
|
+
->(e, s) {
|
10
|
+
c, s2 = m.(e, s)
|
11
|
+
match(c,
|
12
|
+
with(Either::Left) {|v| [c, s2]},
|
13
|
+
with(Either::Right) {|v|
|
14
|
+
blk.call(v).(e, s2)
|
15
|
+
})
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def return(val)
|
20
|
+
->(e, s) { [EitherM.return(val), s] }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/monadt/state.rb
ADDED
data/lib/monadt.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'monadt/maybe'
|
2
|
+
require 'monadt/either'
|
3
|
+
require 'monadt/state'
|
4
|
+
require 'monadt/reader_state_either'
|
5
|
+
require 'monadt/monad'
|
6
|
+
|
7
|
+
module Monadt
|
8
|
+
class Monad
|
9
|
+
class << self
|
10
|
+
def maybe(&blk)
|
11
|
+
do_m(MaybeM, &blk)
|
12
|
+
end
|
13
|
+
|
14
|
+
def present(&blk)
|
15
|
+
do_m(PresentM, &blk)
|
16
|
+
end
|
17
|
+
|
18
|
+
def either(&blk)
|
19
|
+
do_m(EitherM, &blk)
|
20
|
+
end
|
21
|
+
|
22
|
+
def state(&blk)
|
23
|
+
do_m(StateM, &blk)
|
24
|
+
end
|
25
|
+
|
26
|
+
def run_state(initial_state, &blk)
|
27
|
+
prc = state(&blk)
|
28
|
+
prc.(initial_state).first
|
29
|
+
end
|
30
|
+
|
31
|
+
def reader(&blk)
|
32
|
+
do_m(ReaderM, &blk)
|
33
|
+
end
|
34
|
+
|
35
|
+
def run_reader(env, &blk)
|
36
|
+
reader(&blk).(env)
|
37
|
+
end
|
38
|
+
|
39
|
+
def reader_state_choice(&blk)
|
40
|
+
do_m(ReaderStateEitherM, &blk)
|
41
|
+
end
|
42
|
+
|
43
|
+
def run_reader_state_choice(env, initial_state, &blk)
|
44
|
+
reader_state_choice(&blk).(env, initial_state).first
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: monadt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Will Pleasant-Ryan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-03-25 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Functions to create ADTs and do pattern matching, as well as Enumerator
|
14
|
+
based Monad computation
|
15
|
+
email: will.ryan@atomicobject.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/monadt.rb
|
21
|
+
- lib/monadt/adt.rb
|
22
|
+
- lib/monadt/either.rb
|
23
|
+
- lib/monadt/list.rb
|
24
|
+
- lib/monadt/maybe.rb
|
25
|
+
- lib/monadt/monad.rb
|
26
|
+
- lib/monadt/reader.rb
|
27
|
+
- lib/monadt/reader_state_either.rb
|
28
|
+
- lib/monadt/state.rb
|
29
|
+
homepage: https://github.com/atomicobject/monadt
|
30
|
+
licenses:
|
31
|
+
- Apache
|
32
|
+
metadata: {}
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 2.4.5
|
50
|
+
signing_key:
|
51
|
+
specification_version: 4
|
52
|
+
summary: ADTs and Monads in Ruby
|
53
|
+
test_files: []
|