Skip to content

Commit 396e82e

Browse files
committed
fixed alpha substitution for implicits
1 parent fb60091 commit 396e82e

File tree

4 files changed

+63
-43
lines changed

4 files changed

+63
-43
lines changed

AST.hs

+9-1
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,21 @@ data PredData = PredData { _dataFamily :: Maybe Name
5555
, _dataPriority :: Integer
5656
, _dataSound :: Bool
5757
}
58-
58+
deriving Show
5959
data FlatPred = FlatPred { _predData :: PredData
6060
, _predName :: Name
6161
, _predValue :: Maybe Term
6262
, _predType :: Type
6363
, _predKind :: Kind
6464
}
65+
instance Show FlatPred where
66+
show (FlatPred a b c d e) = "FlatPred ("
67+
++show a++") ("
68+
++show b++") ("
69+
++show c++") ("
70+
++show d++") ("
71+
++show e++") ("
72+
6573
$(makeLenses ''PredData)
6674
$(makeLenses ''FlatPred)
6775
$(makeLenses ''Decl)

HOU.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ typeCheckAxioms verbose lst = do
818818
inferAll $ case val of
819819
Just (val,_,_) -> ((M.insert nm val lv, sub' <$> lt), (resp & predValue .~ Just val) :r , sub <$> toplst)
820820
where sub' (b,a) = (b, sub a)
821-
sub :: Subst a => a -> a
821+
sub :: (Show a, Subst a) => a -> a
822822
sub = subst $ nm |-> ascribe val (dontcheck ty)
823823
_ -> ((lv, lt), resp:r, toplst)
824824

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ defn subtract : num -> num -> num -> prop
9696
query main = run $ do
9797
, putStr "hey!\n"
9898
, readLine (\A . do
99-
, putStr A
100-
, putStr "\nbye!\n")
99+
, putStr A
100+
, putStr "\nbye!\n")
101101
```
102102

103103
* Higher order logic programming: like in twelf and lambda-prolog. This makes HOAS much easier to do.

Substitution.hs

+51-39
Original file line numberDiff line numberDiff line change
@@ -66,50 +66,62 @@ findTyconInPrefix nm = fip []
6666
apply :: Spine -> Spine -> Spine
6767
apply !a !l = rebuildSpine a [l]
6868

69-
rebuildSpine :: Spine -> [Spine] -> Spine
70-
rebuildSpine s [] = s
71-
rebuildSpine (Spine "#imp_abs#" [_, Abs nm ty rst]) apps = case findTyconInPrefix nm apps of
72-
Just (v, apps) -> rebuildSpine (Abs nm ty rst) (v:apps)
73-
Nothing -> seq sp $ if ty == atom && S.notMember nm (freeVariables rs) then rs else irs
74-
-- proof irrelevance hack
75-
-- we know we can prove that type "prop" is inhabited
76-
-- irs - the proof doesn't matter
77-
-- rs - the proof matters
78-
-- irs - here, the proof might matter, but we don't know if we can prove the thing,
79-
-- so we need to try
80-
where nm' = newNameFor nm $ freeVariables apps
81-
sp = subst (nm |-> var nm') rst
82-
rs = rebuildSpine sp apps
83-
irs = infer nm ty rs
84-
rebuildSpine (Spine c apps) apps' = Spine c $ apps ++ apps'
85-
rebuildSpine (Abs nm _ rst) (a:apps') = let sp = subst (nm |-> a) $ rst
86-
in seq sp $ rebuildSpine sp apps'
8769

8870
newNameFor :: Name -> S.Set Name -> Name
8971
newNameFor nm fv = nm'
9072
where nm' = fromJust $ find free $ nm:map (\s -> show s ++ "/?") [0..]
9173
free k = not $ S.member k fv
9274

9375
newName :: Name -> Map Name Spine -> S.Set Name -> (Name, Map Name Spine, S.Set Name)
94-
newName "" so fo = ("",so,fo)
95-
newName nm so fo = (nm',s',f')
96-
where s = M.delete nm so
76+
newName "" so fo = ("",so, S.delete "" fo)
77+
newName nm so fo' = (nm',s',f')
78+
where fo = S.delete nm fo'
79+
s = M.delete nm so
9780
-- could reduce the size of the free variable set here, but for efficiency it is not really necessary
9881
-- for beautification of output it is
99-
(s',f') = if nm == nm' then (s,fo) else (M.insert nm (var nm') s , S.insert nm' fo)
82+
(s',f') = if nm == nm' then (s,fo) else (M.insert nm (var nm') s , fo)
10083
nm' = fromJust $ find free $ nm:map (\s -> show s ++ "/") [0..]
10184
fv = mappend (M.keysSet s) (freeVariables s)
10285
free k = not $ S.member k fv
10386

104-
class Subst a where
105-
substFree :: Substitution -> S.Set Name -> a -> a
87+
88+
freeWithout sp [] = freeVariables sp
89+
freeWithout (Abs nm tp rst) (a:lst) = S.delete nm $ freeWithout rst lst
90+
freeWithout (Spine "#imp_abs#" [_, Abs nm tp rst]) apps = case findTyconInPrefix nm apps of
91+
Just (v,apps) -> S.delete nm $ freeWithout rst apps
92+
Nothing -> S.delete nm $ freeWithout rst apps
93+
freeWithout l apps = freeVariables l
94+
10695

107-
subst :: Subst a => Substitution -> a -> a
108-
subst s = substFree s $ freeVariables s
96+
subst :: (Show a, Subst a) => Substitution -> a -> a
97+
subst s a = substFree s mempty a
10998

99+
class Subst a where
100+
substFree :: Substitution -> S.Set Name -> a -> a
101+
110102
class Alpha a where
111103
alphaConvert :: S.Set Name -> Map Name Name -> a -> a
112104
rebuildFromMem :: Map Name Name -> a -> a
105+
106+
107+
rebuildSpine :: Spine -> [Spine] -> Spine
108+
rebuildSpine s [] = s
109+
rebuildSpine (Spine "#imp_abs#" [_, Abs nm ty rst]) apps = case findTyconInPrefix nm apps of
110+
Just (v, apps) -> rebuildSpine (Abs nm ty rst) (v:apps)
111+
Nothing -> seq sp $ if ty == atom && S.notMember nm (freeVariables rs) then rs else irs
112+
-- proof irrelevance hack
113+
-- we know we can prove that type "prop" is inhabited
114+
-- irs - the proof doesn't matter
115+
-- rs - the proof matters
116+
-- irs - here, the proof might matter, but we don't know if we can prove the thing,
117+
-- so we need to try
118+
where nm' = newNameFor nm $ freeVariables apps
119+
sp = substFree (nm |-> var nm') mempty rst
120+
rs = rebuildSpine sp apps
121+
irs = infer nm ty rs
122+
rebuildSpine (Spine c apps) apps' = Spine c $ apps ++ apps'
123+
rebuildSpine (Abs nm _ rst) (a:apps') = let sp = substFree (nm |-> a) mempty rst
124+
in seq sp $ rebuildSpine sp apps'
113125

114126
instance Subst a => Subst [a] where
115127
substFree s f t = substFree s f <$> t
@@ -120,24 +132,24 @@ instance Alpha a => Alpha [a] where
120132

121133
instance (Subst a, Subst b) => Subst (a,b) where
122134
substFree s f ~(a,b) = (substFree s f a , substFree s f b)
123-
135+
124136
instance Subst Spine where
125-
substFree s f sp@(Spine "#imp_forall#" [_, Abs nm tp rst]) = case "" /= nm && S.member nm f && not (S.null $ S.intersection (M.keysSet s) $ freeVariables sp) of
126-
False -> imp_forall nm (substFree s f tp) $ substFree (M.delete nm s) f rst
127-
True -> error $
128-
"can not capture free variables because implicits quantifiers can not alpha convert: "++ show sp
129-
++ "\n\tfor: "++show s
130-
substFree s f sp@(Spine "#imp_abs#" [_, Abs nm tp rst]) = case "" /= nm && S.member nm f && not (S.null $ S.intersection (M.keysSet s) $ freeVariables sp) of
131-
False -> imp_abs nm (substFree s f tp) $ substFree (M.delete nm s) f rst
132-
True -> error $
133-
"can not capture free variables because implicit binds can not alpha convert: "++ show sp
134-
++ "\n\tfor: "++show s
137+
substFree s f sp@(Spine "#imp_forall#" [_, Abs nm tp rst]) =
138+
imp_forall nm (substFree s f tp) $ substFree (M.delete nm s) (S.insert nm f) rst
139+
140+
substFree s f sp@(Spine "#imp_abs#" [_, Abs nm tp rst]) =
141+
imp_abs nm (substFree s f tp) $ substFree (M.delete nm s) (S.insert nm f) rst
135142
substFree s f (Abs nm tp rst) = Abs nm' (substFree s f tp) $ substFree s' f' rst
136143
where (nm',s',f') = newName nm s f
137144
substFree s f (Spine "#tycon#" [Spine c [v]]) = Spine "#tycon#" [Spine c [substFree s f v]]
138-
substFree s f (Spine nm apps) = let apps' = substFree s f <$> apps in
145+
substFree s f sp@(Spine nm apps) = let apps' = substFree s f <$> apps in
139146
case s ! nm of
140-
Just nm -> rebuildSpine nm apps'
147+
Just new -> case S.null $ S.intersection f (freeWithout new apps') of
148+
True -> rebuildSpine new apps'
149+
False -> error $
150+
"can not capture free variables because implicits quantifiers can not alpha convert: "++ show sp
151+
++ "\n\tfor: "++show s
152+
++ "\n\tbound by: "++show f
141153
_ -> Spine nm apps'
142154

143155
instance Alpha Spine where

0 commit comments

Comments
 (0)