Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parsing Haskell—解析表达式中变量的状态(变量是否绑定?)_Parsing_Variables_Haskell - Fatal编程技术网

Parsing Haskell—解析表达式中变量的状态(变量是否绑定?)

Parsing Haskell—解析表达式中变量的状态(变量是否绑定?),parsing,variables,haskell,Parsing,Variables,Haskell,嗨,我得到了一个函数,它接受一个字符串并计算值,可以是int,也可以是bool。字符串可以是:“*让X=3 in+x12”,表示“(让X=3 in(X+1))*2”。如果我要一个bool的话,它会给我8或false。很简单。但我还想检查解析器中绑定变量的状态。也就是说,如果我使用这样的字符串“*让X=3 in+x1 X”作为输入,它将表示“(让X=3 in(X+1))*X”,这将使最后一个X解除绑定。这将给我一个错误,说变量A是未绑定的或其他什么。 如果有人能给我一些关于如何做到这一点的想法,我

嗨,我得到了一个函数,它接受一个字符串并计算值,可以是int,也可以是bool。字符串可以是:“
*让X=3 in+x12
”,表示“
(让X=3 in(X+1))*2
”。如果我要一个bool的话,它会给我8或false。很简单。但我还想检查解析器中绑定变量的状态。也就是说,如果我使用这样的字符串“
*让X=3 in+x1 X
”作为输入,它将表示“
(让X=3 in(X+1))*X
”,这将使最后一个X解除绑定。这将给我一个错误,说变量A是未绑定的或其他什么。 如果有人能给我一些关于如何做到这一点的想法,我将不胜感激

解析字符串的EXPAMPEL:

((X=3 in(X+1))*2)

将给我:

(Mul(Let(Vari X)(Lit(Single 3))(Sum(Vari X)(Lit(Single 1))))(Vari X))

所以我的问题基本上是如何检查解析的字符串是否有任何未绑定的变量

data Number = Single Int | Many Int Number deriving (Eq, Show)

data Expr = Vari Chara | Lit Number | Sub Expr | Sum Expr Expr | Mul Expr Expr | Let Expr Expr Expr | If Expr Expr Expr deriving (Eq, Show)

递归解析后的表达式,保留一组绑定变量。每次遇到
时,记录它,每次遇到
Var
时,检查它是否在您的集合中,每次遇到其他内容时,检查它的子表达式

checkVars' :: Set String -> Expr -> Bool
checkVars' bound (Var v) = S.member v set
checkVars' bound (Let var val expr) = checkVars' bound val && checkVars' (insert var bound) expr
checkVars' bound (Mul expr1 expr2) = checkVars' bound expr1 && checkVars' bound expr2
-- Similar for other ctors...

checkVars :: Expr -> Bool
checkVars = checkVars' S.empty
您也可以朝相反的方向工作,自下而上构建一组自由变量,并在看到变量被
Let
绑定时删除它们。(这感觉更自然。)


递归解析后的表达式,保留一组绑定变量。每次遇到
时,记录它,每次遇到
Var
时,检查它是否在您的集合中,每次遇到其他内容时,检查它的子表达式

checkVars' :: Set String -> Expr -> Bool
checkVars' bound (Var v) = S.member v set
checkVars' bound (Let var val expr) = checkVars' bound val && checkVars' (insert var bound) expr
checkVars' bound (Mul expr1 expr2) = checkVars' bound expr1 && checkVars' bound expr2
-- Similar for other ctors...

checkVars :: Expr -> Bool
checkVars = checkVars' S.empty
您也可以朝相反的方向工作,自下而上构建一组自由变量,并在看到变量被
Let
绑定时删除它们。(这感觉更自然。)

我建议在带有绑定的语法中对变量(如提供的)使用本地匿名表示。在本地匿名表示中,绑定变量使用de Bruijn索引表示,未绑定变量使用名称表示。当涉及到alpha等价和捕获避免替换等问题时,这为您节省了大量的精力,并且回答“这个变量有界吗?”的问题变得非常简单

通常,本地无名表示是曲面语法树上范围检查操作的输出。我们可以从中调整代码,以生成选中的术语,而不是
Bool

data Scoped a = SVar a
              | SLet (Scoped a) (Scope () Scoped a)  -- The expression being let-bound, and the subexpression with the new variable in scope
              | SLit Number
              | SSub (Scoped a)
              | SSum (Scoped a) (Scoped a)
              | SMul (Scoped a) (Scoped a)
              | SIf (Scoped a) (Scoped a) (Scoped a)
              deriving (Functor, Foldable, Traversable)

instance Applicative Scoped where
    pure = SVar
    (<*>) = ap

instance Monad Scoped where
    return = SVar
    SVar a >>= g = g a
    SLet expr scope >>= g = SLet (expr >>= g) (scope >>>= g)
    SLit x >>= g = SLit x
    SSub x >>= g = SSub (x >>= g)
    SSum x y >>= g = SSum (x >>= g) (y >>= g)
    SMul x y >>= g = SMul (x >>= g) (y >>= g)
    SIf cond t f >>= g = SIf (cond >>= g) (t >>= g) (f >>= g)

scoped :: Expr -> Scoped Char
scoped (Var x) = SVar x
scoped (Let name expr sub) = SLet (scope expr) (abstract1 name $ scoped sub)
scoped (Lit x) = SLit x
scoped (Sub s) = SSub (scoped s)
scoped (Sum x y) = SSum (scoped x) (scoped y)
scoped (Mul x y) = SMul (scoped x) (scoped y)
scoped (If cond t f) = SIf (scoped cond) (scoped t) (scoped f)
bound
的combinator正是您想要的:如果表达式有任何自由变量,它将返回
False

data Number = Single Int | Many Int Number deriving (Eq, Show)

data Expr = Vari Chara | Lit Number | Sub Expr | Sum Expr Expr | Mul Expr Expr | Let Expr Expr Expr | If Expr Expr Expr deriving (Eq, Show)
在作用域下行走时,如果需要知道某个特定变量是绑定的还是自由的,则可以在的
B
F
构造函数上进行模式匹配,或者使用:

有关
绑定
工作原理的详细信息,请参阅或。

我建议在带有绑定的语法中对变量(如提供的)使用本地匿名表示。在本地匿名表示中,绑定变量使用de Bruijn索引表示,未绑定变量使用名称表示。当涉及到alpha等价和捕获避免替换等问题时,这为您节省了大量的精力,并且回答“这个变量有界吗?”的问题变得非常简单

通常,本地无名表示是曲面语法树上范围检查操作的输出。我们可以从中调整代码,以生成选中的术语,而不是
Bool

data Scoped a = SVar a
              | SLet (Scoped a) (Scope () Scoped a)  -- The expression being let-bound, and the subexpression with the new variable in scope
              | SLit Number
              | SSub (Scoped a)
              | SSum (Scoped a) (Scoped a)
              | SMul (Scoped a) (Scoped a)
              | SIf (Scoped a) (Scoped a) (Scoped a)
              deriving (Functor, Foldable, Traversable)

instance Applicative Scoped where
    pure = SVar
    (<*>) = ap

instance Monad Scoped where
    return = SVar
    SVar a >>= g = g a
    SLet expr scope >>= g = SLet (expr >>= g) (scope >>>= g)
    SLit x >>= g = SLit x
    SSub x >>= g = SSub (x >>= g)
    SSum x y >>= g = SSum (x >>= g) (y >>= g)
    SMul x y >>= g = SMul (x >>= g) (y >>= g)
    SIf cond t f >>= g = SIf (cond >>= g) (t >>= g) (f >>= g)

scoped :: Expr -> Scoped Char
scoped (Var x) = SVar x
scoped (Let name expr sub) = SLet (scope expr) (abstract1 name $ scoped sub)
scoped (Lit x) = SLit x
scoped (Sub s) = SSub (scoped s)
scoped (Sum x y) = SSum (scoped x) (scoped y)
scoped (Mul x y) = SMul (scoped x) (scoped y)
scoped (If cond t f) = SIf (scoped cond) (scoped t) (scoped f)
bound
的combinator正是您想要的:如果表达式有任何自由变量,它将返回
False

data Number = Single Int | Many Int Number deriving (Eq, Show)

data Expr = Vari Chara | Lit Number | Sub Expr | Sum Expr Expr | Mul Expr Expr | Let Expr Expr Expr | If Expr Expr Expr deriving (Eq, Show)
在作用域下行走时,如果需要知道某个特定变量是绑定的还是自由的,则可以在的
B
F
构造函数上进行模式匹配,或者使用:


有关
bound
如何工作的更多信息,请参阅或。

IMHO在解析后,此检查应在更高级别上进行。是的,我想是这样,我至少会让它更容易。我认为您的
Let
构造函数设置不正确。在e2
中,让x=e1在
=
中位于
=
左侧的东西是一个名称(或者更一般地说,是一个_模式),而不是一个任意表达式
let(如果是foo,那么bar else baz)=x在y中
没有意义!我想在解析之后,这个检查应该在更高的层次上进行。是的,我想是的,我至少会让它更容易。我认为你的
Let
构造函数设置不正确。在e2
中,让x=e1在
=
中位于
=
左侧的东西是一个名称(或者更一般地说,是一个_模式),而不是一个任意表达式
let(如果是foo,那么bar else baz)=x在y中
没有意义!好吧,我不能让它工作。我以前没有和set合作过,所以我不知道该怎么做。我想我知道发生了什么,但我不能让它工作。(编辑,我在我的问题中添加了更多的代码)@HNTW我觉得自上而下的遍历更自然。如果您采用类型化方法,即范围检查生成一个带有本地无名表示的表达式,那么您需要重写
Var
节点(用de Bruijn索引替换它们),这在从上到下遍历时要容易得多。好的,我无法实现这一点。我以前没有和set合作过,所以我不知道该怎么做。我想我知道发生了什么,但我不能让它工作。(编辑,我在我的问题中添加了更多的代码)@HNTW我觉得自上而下的遍历更自然。如果您采用类型化方法,则范围检查将生成一个表达式