-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathadt.edh
123 lines (97 loc) · 2.01 KB
/
adt.edh
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# %%
data D0 () pass
d0 = D0()
# %%
data D1 d pass
d1 = D1( 333 )
# %%
data D2 ( d1, d2 ) pass
d2 = D2( 333, 777 )
# %%
data D3 ( d1, d2, d3 ) pass
d3 = D3( 333, 777, 555 )
# %%
data D( a, b, c, d ) pass
d = D( 3, 2, 5, 11 )
# %%
assert$ d is not D( 3, 2, 5, 11 )
assert$ d == D( 3, 2, 5, 11 )
assert$ d > D( 3, 1, 5, 9 )
d <= D( 3, 1, 5, 9 )
# %%
case d of { D( a, b= bAsMatched, c ) } -> {
'got a=' ++ a ++ ', bAsMatched=' ++ bAsMatched ++ ', c=' ++ c
}
# %{
# data classes can be used to simulate ADT in Haskell, but due to it's openness
# nature, exhaustiveness detection is not possible. While this should not be
# surprising as Edh is highly dynamicly typed, as so generally lacks type-safty
# compared to Haskell.
# %%
data SomeNumber (*** _ ) {
n = nan
}
data One () { extends SomeNumber
n = 1
}
data Two () { extends SomeNumber
n = 2
}
data Three () { extends SomeNumber
n = 3
}
data Many ( n=4 ) { extends SomeNumber
method __init__(*** _ ) {
if not ( this.n > 3 )
then throw UsageError( 'bad Many() for n to be ' ++ this.n )
}
}
v = Many( 99 )
# %%
case v of {
{ SomeNumber( n ) } -> {
console.info<| "We know it's numeric value is " ++ n ++ ' now'
{ { One:_ } } -> {
'got 1'
}
{ { Two:_ } } -> {
'got 2'
}
{ { Three:_ } } -> {
'got 3'
}
{ { Many:m } } | m.n > 999 -> {
'got too many'
}
_ -> {
'got as many as ' ++ v.n
}
}
_ -> {
"it's not some number"
}
}
# %%
Many( -1 )
# %}
# %%
Point :: ( Decimal, Decimal ) -> Point
data Point( x, y ) pass
Circle :: ( Point, Decimal ) -> Circle
data Circle( center, radius ) {
property$
method area() 3.14 * this.radius**2
}
# %%
origin = Point( 0, 0 )
unit = Point( 1, 1 )
c1 = Circle( Point( 3, 5 ), 2.61 )
# %%
assert$ c1 == Circle( Point( 3, 5 ), 2.61 )
assert$ c1 != Circle( Point( 3, 5 ), 2.60 )
# %%
case c1.center of {@
{ { Point: c } } | abs( c.x ) > 1 && abs( c.y ) > 1
-> console.print( 'Got a circle far enough with area '
++ c1.area ++ ' : ' ++ c1 )
@}