[英]Writing a recursive function for renaming terms in lambda calculus
I've made an attempt at writing a function that will rename variable names in a Lambda calculus term.我尝试编写一个函数,该函数将重命名 Lambda 演算术语中的变量名称。 The renaming operation is M[y/x] (M with x renamed to y).
重命名操作是 M[y/x](M 将 x 重命名为 y)。
The problem lies, in these lines of code, | z == x = y
问题在于,在这些代码行中,
| z == x = y
| z == x = y
, where newN = rename(n)
, where newZ1 = rename(newZ1)
and newZ2 = rename(newZ2)
. | z == x = y
, where newN = rename(n)
, where newZ1 = rename(newZ1)
和newZ2 = rename(newZ2)
。
| z == x = y
| z == x = y
comes up with a type error Expected type: Term Actual type: Var
. | z == x = y
出现类型错误Expected type: Term Actual type: Var
。 Please can you help me to understand why I get this error?请你能帮我理解为什么我会收到这个错误吗?
The other three errors come from when I attempt to recursively call the rename function.其他三个错误来自我尝试递归调用重命名函数时。 I get the error
• Probable cause: 'rename' is applied to too few arguments
.我收到错误
• Probable cause: 'rename' is applied to too few arguments
。 When I was writing this I thought that it would rename the Variable to according to the case which was set for a Variable.当我写这篇文章时,我认为它会根据为变量设置的大小写来重命名变量。 How do I do this correctly, cheers.
我如何正确地做到这一点,欢呼。
type Var = String
data Term =
Variable Var
| Lambda Var Term
| Apply Term Term
-- deriving Show
instance Show Term where
show = pretty
example :: Term
example = Lambda "a" (Lambda "x" (Apply (Apply (Lambda "y" (Variable "a")) (Variable "x")) (Variable "b")))
pretty :: Term -> String
pretty = f 0
where
f i (Variable x) = x
f i (Lambda x m) = if i /= 0 then "(" ++ s ++ ")" else s where s = "\\" ++ x ++ ". " ++ f 0 m
f i (Apply n m) = if i == 2 then "(" ++ s ++ ")" else s where s = f 1 n ++ " " ++ f 2 m
rename :: Var -> Var -> Term -> Term
rename x y (Variable z)
| z == x = y
| otherwise = (Variable z)
rename x y (Lambda z n)
| z == x = (Lambda z n)
| otherwise = (Lambda z newN)
where newN = rename(n)
rename x y (Apply n m) = (Apply newZ1 newZ2)
where newZ1 = rename(newZ1)
newZ2 = rename(newZ2)
The reasons for the errors are exactly as the messages say.错误的原因与消息所说的完全一样。 I'll go through them, after quoting the whole of the faulty definition:
在引用整个错误定义后,我将仔细阅读它们:
rename :: Var -> Var -> Term -> Term
rename x y (Variable z)
| z == x = y
| otherwise = (Variable z)
rename x y (Lambda z n)
| z == x = (Lambda z n)
| otherwise = (Lambda z newN)
where newN = rename(n)
rename x y (Apply n m) = (Apply newZ1 newZ2)
where newZ1 = rename(newZ1)
newZ2 = rename(newZ2)
The first error, as you report, is type error Expected type: Term Actual type: Var
, on the line | z == x = y
第一个错误,正如你所报告的,是
type error Expected type: Term Actual type: Var
,就行| z == x = y
| z == x = y
. | z == x = y
。
This is entirely due to the return value in that case, y
, which is of type Var
.这完全是由于这种情况下的返回值
y
是Var
类型。 Yet your signature says the return value must have type Term
.然而你的签名说返回值必须是
Term
类型。 This can be fixed by replacing y
with Variable y
, exactly as you have done with z
on the following line.这可以通过用
Variable y
替换y
来解决,正如您在下一行中对z
所做的那样。
As for the other ones, again GHC's suggestion seems to me to be spot on: you haven't applied rename
to enough arguments when making your recursive calls.至于其他的,在我看来 GHC 的建议再次正确:在进行递归调用时,您没有对足够的参数应用
rename
。 rename
has type Var -> Var -> Term -> Term
, which means when applied to a single argument (presumed to be of type Var
), as in your rename(n)
(which can be more concisely written as rename n
), you get a value of type Var -> Term -> Term
, not one of type Term
as you clearly want. rename
类型为Var -> Var -> Term -> Term
,这意味着当应用于单个参数(假定为Var
类型)时,如在您的rename(n)
(可以更简洁地写为rename n
),你得到一个Var -> Term -> Term
类型的值,而不是你明确想要的Term
类型。 To get that, you have to apply rename
to 3 arguments (of the appropriate types), not just 1.为此,您必须将
rename
应用于 3 个(适当类型的)参数,而不仅仅是 1 个。
The following will fix the mentioned errors - although I haven't tested it to see if there are any more errors, nor am I totally sure I've understood the intended behaviour of your function (although I am somewhat confident on that).以下将修复提到的错误 - 尽管我没有测试它以查看是否还有更多错误,我也不完全确定我已经理解您的函数的预期行为(尽管我对此有些信心)。
I have also removed some unnecessary parentheses, and redefined newZ1
and newZ2
to be what I believed you intended, rather than being defined in terms of themselves.我还删除了一些不必要的括号,并将
newZ1
和newZ2
重新定义为我认为你想要的,而不是根据它们本身来定义。
rename :: Var -> Var -> Term -> Term
rename x y (Variable z)
| z == x = Variable y
| otherwise = Variable z
rename x y (Lambda z n)
| z == x = Lambda z n
| otherwise = Lambda z newN
where newN = rename x y n
rename x y (Apply n m) = Apply newZ1 newZ2
where newZ1 = rename x y n
newZ2 = rename x y m
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.