如何解决Ocaml 类型不匹配?预期单位但已定义类型
我收到下面的错误,我不知道为什么会这样。任何帮助表示赞赏。该程序是 Ocaml 中的解释器。 tryOcaml 加下划线的代码段是代码的最后一位“处理器令牌 [];;”不知道为什么会出现类型不匹配或代码中发生不匹配的地方。
错误:此表达式的类型为 stackValue 列表 但是需要一个单元类型的表达式
type stackValue = NUM of int | BOOL of bool | ERROR | STRING of string | NAME of string | UNIT
type com = PUSH of stackValue | POP | ADD | SUB | MUL | DIV | REM | NEG | SWAP | QUIT | TOSTRING | PRINTLN (*| CAT | AND | OR | NOT | LESSTHAN | EQUAL | IF | BIND let com {com} end | funBind com {com} [return] funEnd | call*)
let interpreter ( (inFile : string),(outFile : string )) : unit =
let ic = open_in inFile
in
let oc = open_out outFile
in
let rec loop_read acc =
try
let l = String.trim(input_line ic) in loop_read (l::acc)
with
| End_of_file -> List.rev acc
in
let ls_str = loop_read []
in
let checkrest s =
match s.[0] with
| '"' -> if s.[(String.length s) -1]='"' then STRING(String.sub s 1 ((String.length s)-2)) else ERROR
| '-' | '0'..'9' -> (try NUM(int_of_string s) with _ ->ERROR)
| '_' | 'a'..'z' | 'A'..'Z' -> NAME(s)
|_ -> ERROR
in
let str2sv s =
match s with
|":true:" -> BOOL(true)
|":false:" -> BOOL(false)
|":unit:" -> UNIT
|":error:" -> ERROR
|_-> checkrest s
in
let str2com s =
match s with
|"quit" -> QUIT
|"add" -> ADD
|"sub" -> SUB
|"mul" -> MUL
|"div" -> DIV
|"rem" -> REM
|"pop" -> POP
|"neg" -> NEG
|"swap" -> SWAP
(*|"cat" -> CAT
|"and" -> AND
|"or" -> OR
|"not" -> NOT
|"lessthan" -> LESSTHAN
|"equal" -> EQUAL
|"if" -> IF
|"bind" -> BIND*)
|"toString" -> TOSTRING
|_ -> if String.sub s 0 4 = "push" then let x = str2sv (String.sub s 5 ((String.length s) -5)) in PUSH(x) else PUSH(ERROR)
in
let tokens = List.map str2com ls_str
in
let sv2str sv =
match sv with
|BOOL(true) -> STRING(":true:")
|BOOL(false) -> STRING(":false:")
|UNIT -> STRING(":unit:")
|ERROR -> STRING(":error:")
|STRING(s) -> STRING(s)
|NAME(s) -> STRING(s)
|NUM(x) -> STRING(string_of_int(x))
in
let file_write value = Printf.fprintf oc "%s\n" value
in
let rec processor comlist stack =
match (comlist,stack) with
|(PUSH(x)::comst,stack) -> processor comst (x::stack)
|(POP::comst,stackValue::reststack) -> processor comst reststack
|(POP::comst,[]) -> processor comst (ERROR::stack)
|(ADD::comst,NUM(a)::NUM(b)::reststack) -> processor comst (NUM(a+b)::reststack)
|(ADD::comst,stack) -> processor comst (ERROR::stack)
|(SUB::comst,NUM(a)::NUM(b)::reststack) -> processor comst (NUM(b-a)::reststack)
|(SUB::comst,stack) -> processor comst (ERROR::stack)
|(MUL::comst,NUM(a)::NUM(b)::reststack) -> processor comst (NUM(a*b)::reststack)
|(MUL::comst,stack) -> processor comst (ERROR::stack)
|(DIV::comst,NUM(a)::NUM(b)::reststack) -> if (NUM(a)=NUM(0)) then (processor comst (ERROR::NUM(a)::NUM(b)::reststack)) else (processor comst (NUM(b/a)::reststack))
|(DIV::comst,stack) -> processor comst (ERROR::stack)
|(REM::comst,NUM(a)::NUM(b)::reststack) -> if (NUM(a)=NUM(0)) then (processor comst (ERROR::NUM(a)::NUM(b)::reststack)) else (processor comst (NUM(b mod a)::reststack))
|(REM::comst,stack) -> processor comst (ERROR::stack)
|(NEG::comst,NUM(a)::reststack) -> processor comst (NUM(-a)::reststack)
|(NEG::comst,stack) -> processor comst (ERROR::stack)
|(SWAP::comst,x::xs::reststack) -> processor comst (xs::x::reststack)
|(SWAP::comst,stack) -> processor comst (ERROR::stack)
|(TOSTRING::comst,x::reststack) -> let s = sv2str x in processor comst (s::reststack)
|(TOSTRING::comst,[]) -> processor comst (ERROR::stack)
|(PRINTLN::comst,x::reststack) -> (match x with
|STRING(x) -> file_write x; processor comst reststack
|_ -> ERROR::stack)
|(PRINTLN::comst,[]) -> processor comst (ERROR::stack)
|(QUIT::comst,stack) -> []
|(_,_) -> []
in
processor tokens [];;
解决方法
让我最小化您的代码以突出问题,
let interpreter ( (inFile : string),(outFile : string )) : unit =
... <snip> ...
let rec processor comlist stack =
match (comlist,stack) with
|(PUSH(x)::comst,stack) -> processor comst (x::stack)
|(QUIT::comst,stack) -> []
... <snip> ...
|(_,_) -> []
in
processor tokens []
花点时间仔细看看上面的代码片段,你看到问题了吗?如果还没有,请回答以下问题:
-
processor
函数返回什么类型的值? -
interpreter
应返回什么类型的值?
例如,考虑processor [] []
,它会返回[]
,因此我们可以看到processor tokens []
是_ list
类型的值,但是您有一个注释{{1} } 表示您的 : unit
应评估为 interpreter input output
类型的值,而不是评估为堆栈。
如果你真的不需要堆栈,你可以忽略它,
unit
其中 ignore (processor tokens [])
是一个简单的函数,大致有以下实现,
ignore
即,它只是忽略它的参数,因此它的类型为 let ignore x = ()
。除了使用 'a -> unit
,您还可以这样写,
ignore
因此您忽略返回的堆栈(约定是在忽略的值前加上下划线)并返回 let _stack = processor tokens [] in
()
值而不是 ()
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。