我试图在OCaml中编写一个更简单的解析器,但是遇到了我无法逾越的问题。我已将代码简化为最少的示例,这给了我相同的错误:
我想在OCaml中编写一个函数,该函数接受一个整数列表并输出一个字符串列表。
规则是,如果连续有两个1
,则输出"eleven"
;如果只有一个1
,则输出"one"
对于其他任何数字,它输出"other"
。这段python代码可以完成这项工作:
def convert(numbers, names):
if len(numbers) == 0:
return names
n = numbers.pop(0)
if n == 1:
if len(numbers) > 0 and numbers[0] == 1:
numbers.pop(0)
names.append("eleven")
else:
names.append("one")
else:
names.append("other")
return convert(numbers, names)
convert([1, 1, 2, 1, 3, 1], [])
# -> ['eleven', 'other', 'one', 'other', 'one']
我在OCaml中的尝试是这样的:
let rec convert (numbers : int list) (names : string list) = function
| [] -> List.rev names
| 1 :: 1 :: t -> convert t ("eleven" :: names)
| 1 :: t -> convert t ("one" :: names)
| _ :: t -> convert t ("other" :: names)
;;
convert [1; 1; 2; 3] [];;
我认为将要发生的是convert
会递归地调用自身:整数列表将变小而列表
更大的字符串,直到没有剩余的整数了:
convert [1; 1; 2; 1; 3; 1] []
-> convert [2; 1; 3; 1] ["eleven"]
-> convert [1; 3; 1] ["other"; "eleven"]
-> convert [3; 1] ["one"; "other"; "eleven"]
-> convert [1] ["other"; "one"; "other"; "eleven"]
-> convert [] ["one"; "other"; "one"; "other"; "eleven"]
-> ["eleven"; "other"; "one"; "other"; "one"]
但是实际发生的是编译错误:
Error: This expression has type int list -> string list
but an expression was expected of type string list
突出显示文本convert t ("eleven" :: names)
这是怎么回事?我不明白为什么这行不通。
答案 0 :(得分:5)
function | ...
实际上是fun x -> match x with | ...
的简写。那就是:
let convert numbers names = function
| ...
等同于
let convert numbers names something_else =
match something_else with
| ...
您的convert
函数因此需要三个参数,并且convert t ("eleven" :: names)
返回一个函数int list -> string list
而不是从第一个分支推断的string list
。
将function
替换为match numbers with
以使其编译:
let rec convert (numbers : int list) (names : string list) =
match numbers with
| [] -> List.rev names
| 1 :: 1 :: t -> convert t ("eleven" :: names)
| 1 :: t -> convert t ("one" :: names)
| _ :: t -> convert t ("other" :: names)
;;
convert [1; 1; 2; 3] [];;