Перекрывающиеся операторы совпадения в OCaml

Сейчас я работаю над домашним заданием. По сути, это очень простая версия символической математики. Следующий фрагмент кода отлично работает.

let rec eval exp (vars:(string * int) list) = match exp with
    | Int n -> n
    | Plus (a, b) -> (eval a vars) + (eval b vars)
    (* ... more match statements ... *)

Например, если я ввожу «eval (Plus (Int 3) (Int 5)) []», он правильно вернет 8. Однако, когда я пытаюсь добавить выражение «let», оно выдает ошибку. Вот фрагмент моей модифицированной функции eval:

(* either returns Some value or None *)
let rec findVar key l = ...

let rec eval exp (vars:(string * int) list) = match exp with
    | Id id -> match (findVar id vars) with
        | Some value -> value
        | None -> raise (Failure ("Unknown variable " ^ id))
    | Int n -> n
    | Plus (a, b) -> (eval a vars) + (eval b vars)
    (* ... more match statements ... *)

(* raises "Error: The variant type option has no constructor Int" *)

Я считаю, что причина в том, что компилятор видит код как:

let rec eval exp (vars:(string * int) list) = match exp with
    | Id id -> match (findVar id vars) with
        | Some value -> value
        | None -> raise (Failure ("Unknown variable " ^ id))
        | Int n -> n
        | Plus (a, b) -> (eval a vars) + (eval b vars)
        (* ... more match statements ... *)

Если моя интуиция верна, что это ошибка, как мне ее исправить?

Если есть другая причина моей ошибки, в чем она?


person JBolton    schedule 17.02.2015    source источник
comment
См. [Здесь] [1]; первый ответ в гугле. [1]: stackoverflow.com/questions/ 257605 /   -  person Frédéric Dumont    schedule 17.02.2015
comment
Вы правы, вы должны заключить свое внутреннее выражение соответствия скобками или началом-концом.   -  person didierc    schedule 17.02.2015


Ответы (1)


вам следует либо ограничить ваши внутренние совпадения скобками (или их синтаксическими эквивалентами begin/end), либо разделить ваш код на отдельные вспомогательные функции. Я определенно предпочитаю последнее.

let rec eval exp (vars : (string * int) list) = match exp with
    | Id id -> eval_var vars id
    | Int n -> n
    | Plus (a, b) -> (eval a vars) + (eval b vars)
    (* ... more match statements ... *)
 and eval_var vars id = match findVar id vars with
    | Some v -> ...
person ivg    schedule 17.02.2015