-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSimpleTypedArith.hs
More file actions
134 lines (107 loc) · 2.52 KB
/
SimpleTypedArith.hs
File metadata and controls
134 lines (107 loc) · 2.52 KB
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
import Data.Set
import Control.Monad.Writer
data Term = TTrue
| TFalse
| Zero
| Succ Term
| Pred Term
| IsZero Term
| IfThenElse Term Term Term
| Wrong
deriving (Ord, Eq, Show, Read)
-- Set requires Ord for the performance...
data Type = T | TNat | TBool
deriving (Eq, Show, Read)
type TypedTerm = (Term, Type)
getType :: Term -> (Maybe Type)
getType TTrue = Just TBool
getType TFalse = Just TBool
getType Zero = Just TNat
getType (Succ n) = do
r <- getType n
if (r == TNat) then (return r) else Nothing
getType (Pred n) = do
r <- getType n
if (r == TNat) then (return r) else Nothing
getType (IsZero n) = do
r <- getType n
if (r == TNat) then (return TBool) else Nothing
getType (IfThenElse x y z) = do
r <- getType x
if (r == TNat)
then Nothing
else do
ry <- getType y
rz <- getType z
if (ry == rz) then return ry else Nothing
eval1 :: Term -> Term
--eval1 (IfThenElse TTrue t1 _) = t1
--eval1 (IfThenElse TFalse _ t2) = t2
eval1 (IfThenElse t t1 t2)
| t == TTrue = t1
| t == TFalse = t2
| (isBadBool t) == True = Wrong
| otherwise = IfThenElse (eval1 t) t1 t2
eval1 (Succ t)
| (isBadNat t) = Wrong
| otherwise = Succ $ eval1 t
eval1 (Pred Zero) = Zero
eval1 (Pred (Succ t)) = t
eval1 (Pred t)
| (isBadNat t) == True = Wrong
| otherwise = Pred $ eval1 t
eval1 (IsZero Zero) = TTrue
eval1 (IsZero (Succ _)) = TFalse
eval1 (IsZero t)
| (isBadNat t) == True = Wrong
| otherwise = IsZero $ eval1 t
isValue :: Term -> Bool
isValue Wrong = True
isValue TTrue = True
isValue TFalse = True
isValue t
| isNum t == True = True
| otherwise = False
isNum :: Term -> Bool
isNum Zero = True
isNum (Succ n) = isNum n
isNum _ = False
isBadNat :: Term -> Bool
isBadNat Wrong = True
isBadNat TTrue = True
isBadNat TFalse = True
isBadNat _ = False
isBadBool :: Term -> Bool
isBadBool Wrong = True
isBadBool t
| isNum t == True = True
| otherwise = False
eval :: Term -> Term
eval t
| isValue t == True = t
| otherwise = eval $ eval1 t
eval' :: Term -> WriterT [Term] IO Term
eval' t = do
tell [t]
if isValue t == True
then return t
else do
t' <- return . eval1 $ t
eval' t'
evalMain :: IO()
evalMain =
do
putStr "TERM > "
t <- getLine
(result, logs) <- runWriterT (eval' (read t))
mapM_ (putStrLn . show) logs
evalMain
checkType :: Term -> WriterT [Term] IO Term
checkType t = do
let checkRes = getType t
if (checkRes == Nothing)
evalMain' :: String -> IO()
evalMain' s =
do
(result, logs) <- runWriterT (eval' (read s))
mapM_ (putStrLn . show) logs