Ocaml Camlp4解析器函数:表达式的类型为int,但表达式的类型应为float
我正在编写一个简单的解析器函数,该函数期望流中有一个项,并返回一个int,但出于某种原因,编译器一直期望浮点值,原因我无法理解;特别是考虑到代码是 我尝试过将这两个变量类型转换为int,通常只是对语法进行修改,但函数太简单了,我不知道到底出了什么问题。我知道,对于普通函数,可以使用Ocaml Camlp4解析器函数:表达式的类型为int,但表达式的类型应为float,ocaml,camlp4,Ocaml,Camlp4,我正在编写一个简单的解析器函数,该函数期望流中有一个项,并返回一个int,但出于某种原因,编译器一直期望浮点值,原因我无法理解;特别是考虑到代码是 我尝试过将这两个变量类型转换为int,通常只是对语法进行修改,但函数太简单了,我不知道到底出了什么问题。我知道,对于普通函数,可以使用let:type->type指定类型,但我不知道如何使用解析器函数 下面是函数: let parse_binary_preference=parser |[]->(整数/浮点数) | [< >] -> 30 在里面
let:type->type
指定类型,但我不知道如何使用解析器函数
下面是函数:
let parse_binary_preference=parser
|[<'Token.Number n>]->int\u of \u float n
| [< >] -> 30
在里面
下面是在案例中使用它的更大背景,这也是问题的一部分(尽管我不认为是):
let parse_binary_preference=parser
|[<'Token.Number n>]->(整数/浮点数)
| [< >] -> 30
在里面
分析器
|[<(前缀,种类)=解析_运算符;
'Token.Kwd op??“预期操作员”;
prec=解析二进制优先级;
“Token.Kwd”(“??”预期“(“在操作员原型中”);
args=parse_first_arg[];
运算符原型中的“Token.Kwd')??“expected')”>]->
我现在刚刚拿到标准
File "parser.ml", line 108, characters 49-50:
Error: This expression has type int but an expression was expected of type
float
类型错误
有人知道为什么会有浮动吗?如何使函数预期为int
编辑:
我现在意识到我现在的措辞很糟糕,但是我意识到程序的上下文决定了函数的类型,我问的是程序中的什么使得它假设函数返回了int。它似乎超出了我发布的范围,因此,我正在更新我的帖子,用与所显示的所有内容相关的代码
以下是完整的相关代码集。首先,我为没有包括这一点表示歉意
token.ml:
类型令牌=
(*小学*)
|字符串标识符|整数编号
(*控制*)
|如果| Else |用于
(*用户操作*)
|二元|一元
parser.ml
let parse_prototype=
让rec parse_args acculator=parser
|[<'Token.Kwd',';'Token.Ident id;e=parse_args(id::acculator)>]->e
|[<>]->蓄能器
在里面
让parse_first_arg累加器=解析器
|[<'Token.Ident id;e=parse_args(id::acculator)>]->e
|[<>]->蓄能器
在里面
让parse_操作符=解析器
|[<'Token.Binary>]->“Binary”,2
|[<'Token.Unary>]->“一元”,1
在里面
让parse_binary_preference=解析器
|[<'Token.Number n>]->(浮点n的整数)(*第108行*)
| [< >] -> 30
在里面
分析器
|[<'令牌.Ident id;
“Token.Kwd”(“??”预期“(“原型中”);
args=parse_first_arg[];
原型中的“Token.Kwd”)??“预期交割”)”>]->
Ast.Prototype(id,数组,of_list(list.rev args))
|[<(前缀,种类)=解析_运算符;
'Token.Kwd op??“预期操作员”;
prec=解析二进制优先级;
“Token.Kwd”(“??”预期“(“在操作员原型中”);
args=parse_first_arg[];
运算符原型中的“Token.Kwd')??“expected')”>]->
让name=prefix^(String.make 1 op)在
让args=Array.of_list(list.rev args)在
(*验证op*的参数数是否正确)
如果Array.length args!=那好吧
raise(Stream.Error“op def中的操作数无效”)
其他的
如果种类==1,则
Ast.Prototype(名称、参数)
其他的
Ast.BinOpPrototype(名称、参数、prec)
| [< >] ->
raise(Stream.Error“原型中需要函数名”)
ast.ml
类型原型=
|字符串*字符串数组的原型
|字符串的BinOpPrototype*字符串数组*int
错误的来源不在您显示的行中:有一个令牌
模块和parse_first_arg
和parse_操作符
函数的实现,使您的代码得以编译
一件可能很奇怪的事情是,您的Token.Number使用浮点作为参数
还要注意,camlp4及其解析器扩展已经被废弃
有人知道为什么会有浮动吗?如何使函数预期为int
嗯,由于您没有显示代码,所以无法告诉您代码哪里出错了,但我至少可以指出您对OCaml工作原理的概念性误解,希望它能帮助您修复代码:)
在OCaml中,没有类型转换,您不能让函数期望任何东西,因为类型是从您编写的代码中推断出来的
例如,这里有一个函数
let number_of_words s = String.count s ~f:(Char.is_whitespace) + 1
它的类型被推断为string->int
,在任何情况下都不能更改它,因为类型基本上是由代码的结构定义的。编译器可以推断函数/表达式适用的最一般上下文
在我们的示例中,编译器知道String.count
接受String
类型的值,因此s
也必须是String
类型,它知道String.count
返回int
类型的值,(+)
只能应用于整数。因此,返回的类型是int
,仅此而已
如果您将在不可接受的环境中应用您的功能
"the phrase has " ^ number_of_words "hello, world"
编译器告诉我们,单词“hello,world”的表达式number>的类型为int
,但它的类型应为
"the phrase has " ^ string_of_int (number_of_words "hello, world")
string_of_int 42
- : string = "42"