-
Notifications
You must be signed in to change notification settings - Fork 0
/
chapter13.2.idr
155 lines (135 loc) · 4.12 KB
/
chapter13.2.idr
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
module Main
import Data.List.Views
import Data.Vect
import Data.Vect.Views
import Data.Nat.Views
import Data.Bits
%default total
data StackCmd : Type -> Nat -> Nat -> Type where
Push : Integer -> StackCmd () height (S height)
Pop : StackCmd Integer (S height) height
Top : StackCmd Integer (S height) (S height)
GetStr : StackCmd String height height
PutStr : String -> StackCmd () height height
Pure : ty -> StackCmd ty height height
(>>=) : StackCmd a height1 height2 -> (a -> StackCmd b height2 height3) -> StackCmd b height1 height3
testAdd : StackCmd Integer a a
testAdd =
do
Push 10
Push 20
val1 <- Pop
val2 <- Pop
Pure (val1 + val2)
runStack : (stk : Vect inHeight Integer) -> StackCmd ty inHeight outHeight -> IO (ty, Vect outHeight Integer)
runStack stk (Push val) = pure ((), val :: stk)
runStack (val :: stk) Pop = pure (val, stk)
runStack (val :: stk) Top = pure (val, val :: stk)
runStack stk GetStr =
do
x <- getLine
pure (x, stk)
runStack stk (PutStr s) =
do
putStrLn s
pure ((), stk)
runStack stk (Pure x) = pure (x, stk)
runStack stk (cmd >>= next) =
do
(cmdRes, newStk) <- runStack stk cmd
runStack newStk (next cmdRes)
data StackIO : Nat -> Type where
Do : StackCmd a height1 height2 -> (a -> Inf (StackIO height2)) -> StackIO height1
namespace StackDo
(>>=) : StackCmd a height1 height2 -> (a -> Inf (StackIO height2)) -> StackIO height1
(>>=) = Do
data Fuel = Dry | More (Lazy Fuel)
partial
forever : Fuel
forever = More forever
run : Fuel -> Vect height Integer -> StackIO height -> IO ()
run (More fuel) stk (Do c f) =
do
(res, newStk) <- runStack stk c
run fuel newStk (f res)
run Dry stk p = pure ()
data StkInput = Number Integer | Add | Subtract | Multiply | Negate | Discard | Duplicate
strToInput : String -> Maybe StkInput
strToInput "" = Nothing
strToInput "add" = Just Add
strToInput "subtract" = Just Subtract
strToInput "multiply" = Just Multiply
strToInput "negate" = Just Negate
strToInput "discard" = Just Discard
strToInput "duplicate" = Just Duplicate
strToInput x = if all isDigit (unpack x) then Just (Number (cast x)) else Nothing
mutual
duplicate : StackIO height
duplicate {height = Z} =
do
PutStr "Fewer elements than 1"
stackCalc
duplicate {height = (S k)} =
do
val1 <- Top
Push val1
PutStr ("Duplicated " ++ show val1)
stackCalc
discard : StackIO height
discard {height = Z} =
do
PutStr "Fewer elements than 1"
stackCalc
discard {height = (S k)} =
do
val1 <- Pop
PutStr ("Discarded " ++ show val1)
stackCalc
negate : StackIO height
negate {height = Z} =
do
PutStr "Fewer elements than 1"
stackCalc
negate {height = (S k)} =
do
val1 <- Pop
Push (-val1)
result <- Top
PutStr (show result)
stackCalc
tryBinary : (Integer -> Integer -> Integer) -> StackIO height
tryBinary op {height = (S (S k))} =
do
val1 <- Pop
val2 <- Pop
Push (val2 `op` val1)
result <- Top
PutStr (show result)
stackCalc
tryBinary _ =
do
PutStr "Fewer elements than 2"
stackCalc
stackCalc : StackIO height
stackCalc =
do
PutStr "> "
input <- GetStr
case strToInput input of
Nothing =>
do
PutStr "Invalid input\n"
stackCalc
Just (Number x) =>
do
Push x
stackCalc
Just Add => tryBinary (+)
Just Subtract => tryBinary (-)
Just Multiply => tryBinary (*)
Just Negate => negate
Just Discard => discard
Just Duplicate => duplicate
partial
main : IO ()
main = run forever [] stackCalc