haskell - Determining if an Exp 'e' isClosed based on free variables? -
i'm not sure start or how write isclosed function below. appreciated! below have far.
isclosed supposed take in value e of type exp , determine if it's closed or not evaluating below:
-- identifiers % expressions , variables type id = string -- "builtin" functions. data op = succ | pred | ifzero deriving (show, ord, eq) -- expressions of l data exp = var id | nat integer | op op | lam id exp | app exp exp deriving (ord, eq, show) -- isclosed e true if , if there no free variables in e -- "free" means variable not declared surrounding %. -- example, in expression -- x (%x. x (%y.xz)) (%y.x) -- there 5 occurrences of x. first "free". second -- parameter % expression , never substituted for. -- third , fourth occurrences refer parameter of -- enclosing % expression. fifth free. -- examples: (%x. %y. x y) closed; (%x. y %y. x y) not since -- first occurrence of y free. isclosed :: exp -> bool isclosed lam{} = true isclosed _ = false
how like:
isclosed :: exp -> bool isclosed exp = go [] exp go bindings (var id) = id `elem` bindings go _ (nat _) = true go _ (op _) = true go bindings (lam id exp) = go (id:bindings) exp go bindings (app fn arg) = go bindings fn && go bindings arg let's give test ride:
*main> isclosed (var "e") false *main> isclosed (lam "e" (var "e")) true *main> isclosed (lam "e" (var "x")) false *main> isclosed (app (lam "e" (var "x")) (nat 3)) false *main> isclosed (app (lam "e" (var "e")) (nat 3)) true alternatively, can first write freevars helper , implement isclosed via that:
isclosed :: exp -> bool isclosed = null . freevars freevars :: exp -> [id] freevars exp = go [] exp go bindings (var id) | id `elem` bindings = [] | otherwise = [id] go _ (nat _) = [] go _ (op _) = [] go bindings (lam id exp) = go (id:bindings) exp go bindings (app fn arg) = go bindings fn ++ go bindings arg and then
*main> freevars (var "e") ["e"] *main> freevars (lam "e" (var "x")) ["x"] *main> freevars (lam "e" (var "e")) [] *main> freevars (app (lam "e" (var "x")) (nat 3)) ["x"] *main> freevars (app (lam "e" (var "e")) (nat 3)) []
Comments
Post a Comment