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
|
module Substitution where
import Data.FiniteMap
import FlatCurry.Annotated.Types
import FlatCurryGoodies (TypeAnn)
type Subst = FM
emptySubst :: Ord a => Subst a b
emptySubst = emptyFM (<)
singleSubst :: Ord a => a -> b -> Subst a b
singleSubst = unitFM (<)
mkSubst :: Ord a => [a] -> [b] -> Subst a b
mkSubst vs es = listToFM (<) (zip vs es)
bind :: Ord a => a -> b -> Subst a b -> Subst a b
bind k v s = addToFM s k v
dom :: Subst a b -> [a]
dom = keysFM
range :: Subst a b -> [b]
range = eltsFM
restrict :: Eq a => [a] -> Subst a b -> Subst a b
restrict vs s = filterFM (\v _ -> v `elem` vs) s
findSubstWithDefault :: Ord a => b -> a -> Subst a b -> b
findSubstWithDefault e v s = lookupWithDefaultFM s e v
compose :: SubstBy b => Subst VarIndex b -> Subst VarIndex b -> Subst VarIndex b
compose s1 s2 = mapFM (\_ e -> subst s1 e) s2 `plusFM`
filterFM (\v _ -> not (v `elemFM` s2)) s1
class SubstBy a where
subst :: Subst VarIndex a -> a -> a
instance SubstBy (AExpr a) where
subst s v@(AVar _ i) = findSubstWithDefault v i s
subst _ l@(ALit _ _) = l
subst s (AComb ty ct c es) = AComb ty ct c (map (subst s) es)
subst s (ALet ty bs e) = ALet ty (map substBind bs) (subst s e)
where substBind (v, ve) = (v, subst s ve)
subst s (AFree ty vs e) = AFree ty vs (subst s e)
subst s (AOr ty e1 e2) = AOr ty (subst s e1) (subst s e2)
subst s (ACase ty ct e bs) = ACase ty ct (subst s e) (map substBranch bs)
where substBranch (ABranch p be) = ABranch p (subst s be)
subst s (ATyped ty e ty') = ATyped ty (subst s e) ty'
instance SubstBy TypeExpr where
subst s v@(TVar i) = findSubstWithDefault v i s
subst s (FuncType ty1 ty2) = FuncType (subst s ty1) (subst s ty2)
subst s (TCons c tys) = TCons c (map (subst s) tys)
subst _ (ForallType _ _) = error "Substitution.substTy: ForallType"
type AExpSubst = Subst VarIndex (AExpr TypeAnn)
type TypeSubst = Subst TVarIndex TypeExpr
unify :: [(TypeExpr, TypeExpr)] -> TypeSubst
unify eqs = case unify' emptySubst eqs of
Nothing -> error $ "Given type equations are not unifiable: " ++ show eqs
Just mgu -> mgu
unify' :: TypeSubst -> [(TypeExpr, TypeExpr)] -> Maybe TypeSubst
unify' sub [] = Just sub
unify' sub (eq@(t1, t2):eqs) = case eq of
(TVar i, TVar j) | i == j -> unify' sub eqs
| otherwise -> replace i t2
(TVar i, _) | i `occursIn` t2 -> Nothing
| otherwise -> replace i t2
(_ , TVar j) | j `occursIn` t1 -> Nothing
| otherwise -> replace j t1
(FuncType u1 u2, FuncType v1 v2) -> unify' sub ([(u1, v1), (u2, v2)] ++ eqs)
(TCons c1 ts1, TCons c2 ts2)
| c1 == c2 &&
length ts1 == length ts2 -> unify' sub (zip ts1 ts2 ++ eqs)
| otherwise -> Nothing
(ForallType _ _, _) -> error "Substitution.unify: ForallType"
(_, ForallType _ _) -> error "Substitution.unify: ForallType"
_ -> Nothing
where
replace k v = unify' (bind k v sub)
(map (\(s, t) -> ( subst (singleSubst k v) s
, subst (singleSubst k v) t)) eqs)
occursIn tv ty = case ty of
TVar i -> tv == i
FuncType ty1 ty2 -> tv `occursIn` ty1 || tv `occursIn` ty2
TCons _ tys -> any (tv `occursIn`) tys
ForallType _ _ -> error "Substitution.occursIn: ForallType"
|