如何将逻辑表示法转换为Haskell语法

时间:2017-10-01 20:16:54

标签: haskell functional-programming

我最近在大学学习了Haskell,我正在通过一系列的练习,这里有一段我​​无法理解的片段:

"对于简单的前缀计算器语言,请考虑以下语法:"

num ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
int ::= num | num int
expr ::= int | - expr | + expr expr | * expr expr

我很困惑如何将其转换为Haskell语法(我是Haskell和函数式编程的完全初学者,请温柔)

我怀疑numintexpr是所有可以使用datatype声明的类型/值,并且他们认为对计算器施加约束。但是我无法理解:如何为固定值声明typedata(不是变量),即0-9?另外,如何在声明中添加-+等符号?

4 个答案:

答案 0 :(得分:7)

不要在代表它的AST的语法中混淆一个字符串。比较字符串

"+ + 3 4 5"

这是你用

给出的语法中的一个字符串
Plus (Plus (Literal 3) (Literal 4)) (Literal 5)

这将是String可以解析为AST的合理的Haskell值。

答案 1 :(得分:4)

  

如何为固定值声明类型或数据(不是变量),即0-9?

您可以定义类型,例如

data Digit = Zero | One | Two | Three | Four | Five | Six | Seven | Eight | Nine deriving (Eq, Show)

这表示问题中的num。显然我们不能使用0, 1, 2, 3, ...,因为它们已被解释为Haskell中的数字。

然后,您可以定义

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

相当于问题中的int。此类型表示一个(Single ...)或更多(Many ...)个数字,它们一起构成一个十进制数字。例如,对于这些数据类型,数字361将为Many Three (Many Six (Single One))

  

另外,如何在声明中添加像 - 或+这样的符号?

无法将这些符号放在类型或数据声明中。但是,您可以使用操作的名称,例如SumSubMul。然后问题语法的expr将转换为

data Expr   = Lit Number
            | Sub Expr Expr
            | Sum Expr Expr
            | Mul Expr Expr
            deriving (Eq, Show)

如果我们有一个字符串"+ (- (2 5) (1 3)) 3",它表示问题的前缀计算器语言中的表达式,它将被解析为Sum (Sub (Lit (Many Two (Single Five))) (Lit (Many One (Single Three)))) (Single Three)

答案 2 :(得分:1)

如果它只是关于建模数据的练习(没有代码),答案包括在语法中添加构造函数名称(以及将文字编号更改为名称)。像

这样的东西
data Num = Zero | One | Two | Three | Four | Five 
         | Six | Seven | Eight | Nine
data Int = Single Num | Multiple Num Int
data Exp = ExpInt Int | ExpMinus Exp Exp | ExpMul Exp Exp
         | ExpMul Exp Exp

由此,您可以编写所有类型的代码,以解析和计算表达式。

答案 3 :(得分:0)

多年前,我很聪明,我宣称我的AST类型为instance NumEqOrd,然后定义AST的数学和比较运算符表达式,以便expr1 + expr2产生有效的AST。使用sevenj的声明,这将写成(+) x y = Sum x y,其中右侧是AST表达式的构造函数。为简洁起见,one = Lit Onetwo = Lit Two。然后你可以编写one + one == two并且运算符将使用正确的优先级生成AST。在那个和let { ... } in ...语法的滥用允许任意缩进之间,我有办法写AST几乎只是玩具命令式语言本身,上面,下面和左边有一些样板。

然而,TA对我的任务进行评分并没有被逗乐,并写道:“这不是Haskell!”