Skip to content

subst captures variables when substitution is with a bound variable #61

@liesnikov

Description

@liesnikov

as of 7ce8463 subst checks that variables substituted for are free but doesn't do anything to avoid capture

subst :: Name b -> b -> a -> a
default subst :: (Generic a, GSubst b (Rep a)) => Name b -> b -> a -> a
subst n u x =
if (isFreeName n)
then case (isvar x :: Maybe (SubstName a b)) of
Just (SubstName m) | m == n -> u
_ -> case (isCoerceVar x :: Maybe (SubstCoerce a b)) of
Just (SubstCoerce m f) | m == n -> maybe x id (f u)
_ -> to $ gsubst n u (from x)
else error $ "Cannot substitute for bound variable " ++ show n
substs :: [(Name b, b)] -> a -> a
default substs :: (Generic a, GSubst b (Rep a)) => [(Name b, b)] -> a -> a
substs ss x
| all (isFreeName . fst) ss =
case (isvar x :: Maybe (SubstName a b)) of
Just (SubstName m) | Just (_, u) <- find ((==m) . fst) ss -> u
_ -> case isCoerceVar x :: Maybe (SubstCoerce a b) of
Just (SubstCoerce m f) | Just (_, u) <- find ((==m) . fst) ss -> maybe x id (f u)
_ -> to $ gsubsts ss (from x)
| otherwise =
error $ "Cannot substitute for bound variable in: " ++ show (map fst ss)

this means that we take terms from pi-forall (https://github.com/sweirich/pi-forall/blob/729c9f4e348bd94090b0415e3391ad8bb1d89305/full/src/Syntax.hs) and run the following:

import Unbound.Generics.LocallyNameless.Name as Unbound

an :: TName
an = Unbound.string2Name "aname"

bn :: TName
bn= Unbound.string2Name "bname"

match = Match (Unbound.bind (PatCon trueName []) (Var bn))

bound :: TName
bound = Unbound.Bn 0 0 -- a bound variable

abound = Unbound.bind an (Case (Var an) [match])
{-|
>>> show abound 
<aname> Case (Var 0@0) [Match (<(PatCon "True" [])> Var bname)]

>>> show $ Unbound.subst bn (Var bound) $ abound
<aname> Case (Var 0@0) [Match (<(PatCon "True" [])> Var 0@0)]
-}

We see that Var 0@0 is captured by the case, the correct result would be

<aname> Case (Var 0@0) [Match (<(PatCon "True" [])> Var 1@0)]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions