Haskell 帮助:用新变量替换 lambda 项中的项! (简单的错误需要修复...)

Haskell help : Replacing terms within a lambda-term with new variables! (Simple mistake needs fixing...)

我正在尝试编写一个函数,当通过时:

variables VX = ["v1",..."vn"]

Term 将分别用 variable from VX 替换传递的 Term 中的所有 Terms

我的功能在一定程度上起作用,例如:

S ((\a. \x. (\y. a c) x b) (\f. \x. x) 0)

它returns:

S (V1 V1 0) 

而不是应该的 return:

S (V1 V2 0) 

这是我的函数和测试。谁能发现我犯的错误?

termToExpression :: [Var] -> Term -> Expression
termToExpression [] a = termToExpr a
termToExpression _ (TermVar y) = ExpressionVar y
termToExpression (x : _) (TermLambda a b) = ExpressionVar x 
termToExpression (x : xs) (TermApp n m) = ExpressionApp (termToExpression (x : xs) n) (termToExpression (x : xs) m)

问题是

ExpressionApp (termToExpression (x : xs) n) (termToExpression (x : xs) m)

进行两次递归调用,直觉上第一个应该 "consume" 任意数量的变量来生成其输出。在那之后,第二个递归调用不应该使用第一个已经 "consumed" 的变量。

从某种意义上说,每次调用都会修改某种状态:变量列表被部分消耗。

要对其建模,您需要首先编写一个辅助递归函数,其中 returns 与新的 lambda 项、尚未使用的变量列表一起。

aux :: [Var] -> Term -> (Expression, [Var])

现在,当您需要对 aux 进行两次递归调用时,您可以进行第一个,从其结果中获取未使用变量的列表,然后使用该列表进行第二次递归调用.

(更高级的解决方案是使用 State [Var] monad,但我猜您想编写一个基本解决方案。)