为什么口译员告诉我"This kind of expression is not allowed as right-hand side of `let rec'"



我编写了一个OCAML程序,该程序通过Parser Combinator解析算术表达式。

type 'a parser = char list -> ('a * (char list)) list
let return (x: 'a): 'a parser = fun input -> [x, input]
let fail: 'a parser = fun _ -> []
let ( >>= ) (p: 'a parser) (f : 'a -> 'b parser): 'b parser =
    fun input -> List.map (fun (x, i) -> f x i) (p input) |> List.flatten
let ( ||| ) (p: 'a parser) (q: 'a parser) = 
    fun input -> (p input) @ (q input)
let token: (char parser) = function
    | x::xs -> [x, xs]
    | [] -> []
let char(c: char): (char parser) =
    token >>= fun x ->
    if x = c then return x else fail
let digit: (char parser) =
    token >>= fun x ->
    if x >= '0' && x <= '9' then return x else fail
let rec many(p: 'a parser): 'a list parser =
    (p >>= fun x ->
    many p >>= fun xs ->
    (return (x::xs))) 
    ||| (return [])
let number = 
    many digit >>= fun x -> 
    return (List.fold_left (fun l r -> l * 10 + (int_of_char r - int_of_char '0')) 0 x)
type expr = Add of (expr * expr)
            | Sub of (expr * expr)
            | Mul of (expr * expr)
            | Div of (expr * expr)
            | Neg of expr

上面的代码运行良好。

let rec expression: expr parser =
    term >>= fun l ->
    (char '+' ||| char '-') >>= fun op ->
    term >>= fun r ->
    if op = '+' then return (Add (l, r)) else return (Sub (l, r))
and term: expr parser =
    factor >>= fun l ->
    (char '*' ||| char '/') >>= fun op ->
    factor >>= fun r ->
    if op = '*' then return (Mul (l, r)) else return (Div (l, r))
and factor: expr parser =
    expression
    ||| (char '(' >>= fun _ ->
        expression >>= fun e ->
        char ')' >>= fun _ ->
        return e)
    ||| (char '-' >>= fun _ ->
        factor >>= fun e -> 
        return (Neg e))

,但此片段中有一个错误

    Error: This kind of expression is not allowed as right-hand side of `let rec'

此页面(链接)说:"编译器仅允许三个可能的构造出现在LET REC的右侧:函数定义,构造函数或懒惰的关键字。"

我认为类型解析器是一个函数而不是值,为什么会发生这种情况?

"函数定义"是指文本fun x ->构造。功能语言考虑

的部分功能应用程序
factor >>= fun l -> ...

redexes,而不是文字值,这意味着当它们出现在简单可变绑定的RHS上时,必须立即对其进行评估,例如

term = factor >>= fun l -> ...

一般而言,由于急切地评估递归定义的RHS会产生无限循环,因此严格的语言通常禁止构造或要求绑定明确懒惰。

右侧应该是"函数定义",而不仅仅是函数。函数定义是fun ->function ...形式的句法结构,包括let f x ...的句法糖。在手册的第6.7.1和7.3节中,更正确的措辞。

相关内容

最新更新