-
Notifications
You must be signed in to change notification settings - Fork 0
/
stl.hs
123 lines (90 loc) · 2.98 KB
/
stl.hs
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
-- Type Checker for the Simply-Typed Lambda Calculus
-- Supported Language Features:
-- Abstractions
-- Application
-- Variables
-- Supported Typing Features:
-- Arrow Types (Function Types)
-- Type Variables
module STLambda
( Term (..)
, Type (..)
, Error (..)
, VContext (..)
, showTerm
, showType
, addBinding
, pushBinding
, shiftBindings
, typeof
)
where
data Term = Abs String Type Term
| App Term Term
| Var Int
data Type = Arrow Type Type
| TVar String
deriving Eq
data Error = ParamMismatch Type Type
| MissingArrow Term
| UnboundVar VContext Int
type Function a b = a -> Maybe b
instance Show Term where
show = showTerm (\a -> Nothing)
instance Show Type where
show = showType
instance Show Error where
show = showError
-- Contexts
type VContext = Function Int (String, Type)
addBinding :: Eq a => Function a b -> a -> b -> Function a b
addBinding f a b = \x -> if x == a then Just b else f x
pushBinding :: VContext -> (String, Type) -> VContext
pushBinding ctx p = addBinding (shiftBindings ctx) 0 p
shiftBindings :: VContext -> VContext
shiftBindings ctx = \x -> ctx (x - 1)
-- Show Functions
showTerm :: VContext -> Term -> String
showTerm ctx (Abs s ty tm) =
"\\" ++ s ++ " : " ++ show ty ++ ". " ++ showTerm ctx' tm
where ctx' = pushBinding ctx (s, ty)
showTerm ctx (App t1 t2) =
"(" ++ showTerm ctx t1 ++ ") (" ++ showTerm ctx t2 ++ ")"
showTerm ctx (Var v) =
case ctx v of
Nothing -> "(Var " ++ show v ++ ")"
Just (s, _) -> s
showType :: Type -> String
showType (Arrow a b) =
case a of
Arrow _ _ -> wparen
_ -> showType a ++ " -> " ++ showType b
where wparen = "(" ++ showType a ++ ") -> " ++ showType b
showType (TVar s) = s
showError :: Error -> String
showError (ParamMismatch t1 t2) = "expected type (" ++ show t1 ++ "), supplied type (" ++ show t2 ++ ")"
showError (MissingArrow t) = "expected arrow type in the term \'" ++ show t ++ "\'"
showError (UnboundVar ctx i) = "variable indexed by \'" ++ show i ++ "\' not in the present context"
-- toFunct
toFunct :: Eq a => [(a, b)] -> Function a b
toFunct [] = \a -> Nothing
toFunct (x:xs) = \n -> if n == a then Just b else (toFunct xs) n where (a, b) = x
-- Typing
typeof :: Term -> Either Error Type
typeof = typeof0 (toFunct [])
typeof0 :: VContext -> Term -> Either Error Type
typeof0 ctx (Abs s ty1 tm) = (Arrow ty1) <$> typeof0 ctx' tm
where ctx' = pushBinding ctx (s, ty1)
typeof0 ctx (App t1 t2) = do
ty1 <- typeof0 ctx t1
ty2 <- typeof0 ctx t2
case ty1 of
Arrow ty11 ty12 ->
if ty11 == ty2
then Right ty12
else Left $ ParamMismatch ty11 ty2
_ -> Left $ MissingArrow (App t1 t2)
typeof0 ctx (Var v) =
case ctx v of
Nothing -> Left $ UnboundVar ctx v
Just (_, t) -> Right t