如何将逻辑符号转换为Haskell语法
我最近在大学学习了Haskell,我正在做一系列练习,下面是一个我无法理解的小片段: 对于简单的前缀计算器语言,请考虑以下语法: 我对如何将其翻译成Haskell语法感到困惑(我是Haskell和函数式编程的完全初学者,请温柔一点)如何将逻辑符号转换为Haskell语法,haskell,functional-programming,Haskell,Functional Programming,我最近在大学学习了Haskell,我正在做一系列练习,下面是一个我无法理解的小片段: 对于简单的前缀计算器语言,请考虑以下语法: 我对如何将其翻译成Haskell语法感到困惑(我是Haskell和函数式编程的完全初学者,请温柔一点) 我怀疑num、int和expr都是可以使用data或type声明的类型/值,它们会对计算器施加约束。但是,我无法理解这两种情况:如何为固定值(即0-9)声明type或data(不是变量)?另外,我如何在声明中放置-或+等符号?不要将语法中的字符串与表示它的AST混淆
我怀疑
num
、int
和expr
都是可以使用data
或type
声明的类型/值,它们会对计算器施加约束。但是,我无法理解这两种情况:如何为固定值(即0-9)声明type
或data
(不是变量)?另外,我如何在声明中放置-
或+
等符号?不要将语法中的字符串与表示它的AST混淆。比较字符串
"+ + 3 4 5"
这是语法中的一个字符串
Plus (Plus (Literal 3) (Literal 4)) (Literal 5)
这将是AST的一个合理的Haskell值,
String
可以解析到该值。不要将语法中的字符串与表示它的AST混淆。比较字符串
"+ + 3 4 5"
这是语法中的一个字符串
Plus (Plus (Literal 3) (Literal 4)) (Literal 5)
这对于AST来说是一个合理的Haskell值,
String
可以解析为它。如果它只是一个关于数据建模的练习(没有代码),那么答案包括将构造函数名称添加到语法中(并将文本数更改为名称)。差不多
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
因此,您可以编写所有类型的代码来解析和计算表达式。如果这只是一个关于数据建模的练习(没有代码),那么答案包括将构造函数名称添加到语法中(并将文本数更改为名称)。差不多
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
由此,您可以编写所有类型的代码来解析和计算表达式
如何为固定值(即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
。此类型表示一个(单个…
)或多个(多个…
)数字,它们一起构成一个十进制数。例如,对于这些数据类型,数字361将是多个三(多个六(单个一))
另外,我如何在声明中放置像-或+这样的符号
无法将这些符号放入类型或数据声明中。但是,您可以为操作使用名称,如Sum
、Sub
和Mul
。然后,问题语法的expr
将转换为
data Expr = Lit Number
| Sub Expr Expr
| Sum Expr Expr
| Mul Expr Expr
deriving (Eq, Show)
如果我们有一个字符串“+((2 5)(1 3))3”
,它表示问题的前缀计算器语言中的一个表达式,它将被解析为总和(Sub(Lit(Many Two(Single Five)))(Lit(Many One(Single Three)))(Single Three)
如何为固定值(即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
。此类型表示一个(单个…
)或多个(多个…
)数字,它们一起构成一个十进制数。例如,对于这些数据类型,数字361将是多个三(多个六(单个一))
另外,我如何在声明中放置像-或+这样的符号
无法将这些符号放入类型或数据声明中。但是,您可以为操作使用名称,如Sum
、Sub
和Mul
。然后,问题语法的expr
将转换为
data Expr = Lit Number
| Sub Expr Expr
| Sum Expr Expr
| Mul Expr Expr
deriving (Eq, Show)
如果我们有一个字符串
“+((2 5)(1 3))3”
,它代表你问题的前缀计算器语言中的一个表达式,它将被解析为和(Sub(Lit(Many-Two(Single-Five)))(Lit(Many-One(Single-Three))(Single-Three)
几年前,我变得聪明了,我将AST类型声明为Num
、Eq
和Ord
的实例,然后定义AST表达式的数学和比较运算符,以便expr1+expr2
将生成有效的AST。使用sevenj的声明,可以像(+)xy=sumxy
那样编写,其中右侧是AST表达式的构造函数。为简洁起见,one=Lit-one
和two=Lit-two
。然后您可以编写one+one==two
,操作符将生成具有正确优先级的AST。在这和滥用let{…}in…
语法以允许任意缩进之间,我有一种编写AST的方法,它几乎就是玩具命令式语言本身,上面、下面和左边都有一些样板
不过,助教给我的作业评分时并不觉得有趣,他写道:“这不是哈斯克尔!”几年前,我变得聪明了,我宣布我的AST类型是Num
、Eq
和Ord
的实例,然后定义了AST表达式的数学和比较运算符,因此,expr1+expr2
将生成有效的AST。使用sevenj的声明,可以像(+)xy=sumxy
那样编写,其中右侧是AST表达式的构造函数。为简洁起见,one=Lit-one
和two=Lit-two
。然后您可以编写one+one==two
,操作符将使用正确的prec生成AST