-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathAST.hs
161 lines (136 loc) · 4.93 KB
/
AST.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
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
156
157
158
159
160
161
{-# LANGUAGE DataKinds, GADTs, KindSignatures, StandaloneDeriving #-}
-- | Abstract syntax
module AST where
import Control.Applicative
import Data.Semigroup
import Data.Monoid
import Data.Set(Set)
import qualified Data.Set as S
-- | Expressions
data Expr
= EVar Var -- ^ x
| EUnit -- ^ ()
| EAbs Var Expr -- ^ \x. e
| EApp Expr Expr -- ^ e1 e2
| EAnno Expr Polytype -- ^ e : A
deriving (Eq, Show)
-- | subst e' x e = [e'/x]e
subst :: Expr -> Var -> Expr -> Expr
subst e' x expr = case expr of
EVar x' | x' == x -> e'
| otherwise -> EVar x'
EUnit -> EUnit
EAbs x' e | x' == x -> EAbs x' e
| otherwise -> EAbs x' (subst e' x e)
EApp e1 e2 -> EApp (subst e' x e1) (subst e' x e2)
EAnno e t -> EAnno (subst e' x e) t
-- Smart constructors
var :: String -> Expr
var = EVar . Var
eunit :: Expr
eunit = EUnit
eabs :: String -> Expr -> Expr
eabs = EAbs . Var
infixr 1 $$
($$) :: Expr -> Expr -> Expr
($$) = EApp
(-:) :: Expr -> Polytype -> Expr
(-:) = EAnno
newtype Var = Var String deriving (Eq, Ord, Show)
newtype TVar = TypeVar String deriving (Eq, Ord, Show)
data TypeKind = Mono | Poly
-- | Types, indexed by their kind: Monotype or Polytype.
-- Only Polytypes can have foralls.
data Type :: TypeKind -> * where
TUnit :: Type a -- ^ ()
TVar :: TVar -> Type a -- ^ alpha
TExists :: TVar -> Type a -- ^ alpha^
TForall :: TVar -> Type Poly -> Type Poly -- ^ forall alpha. A
TFun :: Type a -> Type a -> Type a -- ^ A -> B
deriving instance Show (Type a)
deriving instance Eq (Type a)
-- Smart constructors
tunit :: Type a
tunit = TUnit
tvar :: String -> Type a
tvar = TVar . TypeVar
exists :: String -> Type a
exists = TExists . TypeVar
tforall :: String -> Polytype -> Polytype
tforall = TForall . TypeVar
(-->) :: Type a -> Type a -> Type a
(-->) = TFun
infixr 1 -->
tforalls :: [TVar] -> Polytype -> Polytype
tforalls = flip (foldr TForall)
type Polytype = Type Poly
type Monotype = Type Mono
-- | Is the type a Monotype?
monotype :: Type a -> Maybe Monotype
monotype typ = case typ of
TUnit -> Just TUnit
TVar v -> Just $ TVar v
TForall _ _ -> Nothing
TExists v -> Just $ TExists v
TFun t1 t2 -> TFun <$> monotype t1 <*> monotype t2
-- | Any type is a Polytype since Monotype is a subset of Polytype
polytype :: Type a -> Polytype
polytype typ = case typ of
TUnit -> TUnit
TVar v -> TVar v
TForall v t -> TForall v t
TExists v -> TExists v
TFun t1 t2 -> TFun (polytype t1) (polytype t2)
-- | The free type variables in a type
freeTVars :: Type a -> Set TVar
freeTVars typ = case typ of
TUnit -> mempty
TVar v -> S.singleton v
TForall v t -> S.delete v $ freeTVars t
TExists v -> S.singleton v
TFun t1 t2 -> freeTVars t1 `mappend` freeTVars t2
-- | typeSubst A α B = [A/α]B
typeSubst :: Type a -> TVar -> Type a -> Type a
typeSubst t' v typ = case typ of
TUnit -> TUnit
TVar v' | v' == v -> t'
| otherwise -> TVar v'
TForall v' t | v' == v -> TForall v' t
| otherwise -> TForall v' (typeSubst t' v t)
TExists v' | v' == v -> t'
| otherwise -> TExists v'
TFun t1 t2 -> TFun (typeSubst t' v t1) (typeSubst t' v t2)
typeSubsts :: [(Type a, TVar)] -> Type a -> Type a
typeSubsts = flip $ foldr $ uncurry typeSubst
data ContextKind = Complete | Incomplete
-- | Context elements, indexed by their kind: Complete or Incomplete.
-- Only Incomplete contexts can have unsolved existentials.
data ContextElem :: ContextKind -> * where
CForall :: TVar -> ContextElem a -- ^ alpha
CVar :: Var -> Polytype -> ContextElem a -- ^ x : A
CExists :: TVar -> ContextElem Incomplete -- ^ alpha^
CExistsSolved :: TVar -> Monotype -> ContextElem a -- ^ alpha^ = tau
CMarker :: TVar -> ContextElem a -- ^ |> alpha^
deriving instance Eq (ContextElem a)
deriving instance Show (ContextElem a)
newtype GContext a = Context [ContextElem a]
deriving Show
type CompleteContext = GContext Complete
type Context = GContext Incomplete
-- | Snoc
(>:) :: GContext a -> ContextElem a -> GContext a
Context gamma >: x = Context $ x : gamma
-- | Context & list of elems append
(>++) :: GContext a -> [ContextElem a] -> GContext a
gamma >++ elems = gamma <> context elems
context :: [ContextElem a] -> GContext a
context = Context . reverse
dropMarker :: ContextElem a -> GContext a -> GContext a
dropMarker m (Context gamma) = Context $ tail $ dropWhile (/= m) gamma
breakMarker :: ContextElem a -> GContext a -> (GContext a, GContext a)
breakMarker m (Context xs) = let (r, _:l) = break (== m) xs in (Context l, Context r)
instance Semigroup (GContext a) where
Context gamma <> Context delta = Context (delta ++ gamma)
instance Monoid (GContext a) where
mempty = Context []
mappend = (<>)