/
variable.rb
99 lines (83 loc) · 1.64 KB
/
variable.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
module ShowVariable
def shows(*args)
define_method :show do
args.each do |a|
self.send(a).get do |state|
puts state
end
end
end
end
end
# T
class Variable
# a -> T a
def initialize(state)
@container = state
end
# <T a> -> IO ()
def show
puts @container
end
# a -> T a
def container
lambda do |state|
Variable.new state
end
end
def self.empty
raise NotImplementedError
end
# <T a> -> (a -> T b) -> T b
# take the state of current variable,
# and derive a new variable from it
def derive(&a_to_tb)
a_to_tb.call(@container)
end
# (a -> b) -> <T a> -> T b
# access the variable's state (pure)
def get(&a_to_b)
Variable.new a_to_b.call(@container)
end
# change the variable's state (impure)
def update!(&a_to_b)
@container = a_to_b.call(@container)
self
end
# <T T a> -> T a
# if the variable's state is itself a variable
# this will unpack the innter variable and use its state (impure)
def unpack!
@container = @container.container
end
#if the variable's state is itself a variable
#this will unpack the inner variable and use its state (pure)
def unpack
Variable.new @container.container
end
end
class IntVariable < Variable
# i -> T i
def initialize(state)
super
end
# T i -> T s
def format(fmt)
StrVariable.new sprintf(fmt, @container)
end
def self.empty
IntVariable.new 0
end
end
class StrVariable < Variable
# s -> T s
def initialize(state)
super
end
def self.empty
StrVariable.new ''
end
def from_int(int)
StrVariable.new "#{int}"
end
end