Haskell中的递归问题

时间:2014-04-12 20:32:51

标签: haskell recursion lambda

我有这个compile函数,它应该接受一个String然后产生一个Expression。

这就是Expression的定义方式:

data Expression = Name Char | Lambda Char Expression | Apply Expression Expression 
        deriving Show

让我们说'编译'功能需要是:

"\\x.\\y.yx"

因此,最后compile函数应该将其作为最终的表达式:

Lambda 'x' (Lambda 'y' (Name 'y') (Name 'x'))

这是compile函数:

compile :: [Char] -> Expression
compile (x:xs) = if [x] == "\\" then Lambda (head xs) (compile (tail xs))
                    else if [x] == "." then compile xs
                    else if null xs then Name x
                    else Name x

目前,此功能可以避免表达式的最后一部分((Name 'x'))。我的问题是:

如果我产生Name,那么这个函数如何继续使用更多Name s我不能继续使用表达式的其余部分调用相同的函数?由于Expression的定义是这样的,如果ExpressionName,它只有一个Name而且没有更多,那么就没有表达式了。

我的意思是,我怎样才能接受Name中的每一个Expression,'告诉' Haskell我想继续寻找Name而不只是在找到Name时停止。

我认为可能创建另一个函数是一个好主意,但我无法弄清楚如何多次调用该函数。事实是,我并不习惯在Haskell中进行递归,我真的需要一些帮助。

我该怎么做?

1 个答案:

答案 0 :(得分:3)

直接在String上使用递归进行解析虽然可行但是很棘手。在你的lambda演算语言中,例如处理(嵌套)括号需要一些小心。

如果你想尝试这一点,至少你应该研究LL parsers如何工作:如何编写LL语法,如何处理先行符号,以及一般的形式语言理论的基础知识。

如果你想通过"来学习这些",请尝试使用Parsec等解析器库。

作为一个小建议:虽然大多数关于lambda演算的论文只使用单字母变量并写例如" XY"对于应用程序,在实现中,您确实需要更长的变量名称,即使它是以应用术语之间需要空格为代价的(例如" x y")。这使得解析器稍微难以编写,但值得付出努力。