Я пытался перевести этот код OCaml

 type bool_expr =
    | Var of string
    | Not of bool_expr
    | And of bool_expr * bool_expr
    | Or of bool_expr * bool_expr;

let rec eval val_vars = function
    | Var x -> List.assoc x val_vars
    | Not e -> not(eval val_vars e)
    | And(e1, e2) -> eval val_vars e1 && eval val_vars e2
    | Or(e1, e2) -> eval val_vars e1 || eval val_vars e2

И вот что я сделал

 datatype bool_expr = Var of string
    | Not of bool_expr
    | And of bool_expr * bool_expr
    | Or of bool_expr * bool_expr;
    
And(Or(Var "a", Var "b"), And(Var "a", Var "b"));

val rec eval vars = 
    fn  Var x => List.assoc x vars
    | Not e => not(eval vars e)
    | And(e1, e2) => eval vars e1 andalso eval vars e2
    | Or(e1, e2) => eval vars e1 orelse eval vars e2

У меня есть ошибки относительно vars в этой строке: 'val rec eval vars =', и я не знаю эквивалента для 'List.assoc' в SML.

0
IndifineGenome 21 Окт 2020 в 01:33

1 ответ

Лучший ответ

Вы можете перевести OCaml в SML, выполнив Сравнение Objective Caml и Standard ML.

Вот одна попытка:

datatype bool_expr =
    Var of string
  | Not of bool_expr
  | And of bool_expr * bool_expr
  | Or of bool_expr * bool_expr

exception NotFound
fun lookup x [] = raise NotFound
  | lookup x ((y,v)::rest) =
      if x = y
      then v
      else lookup x rest

fun eval val_vars = fn
    Var x => lookup x val_vars
  | Not e' => not (eval val_vars e')
  | And (e1, e2) => eval val_vars e1 andalso eval val_vars e2

В SML вы хотите сделать следующее:

  • Используйте ключевое слово datatype для определения алгебраического типа данных, а не OCaml type.

  • Используйте fn вместо function как для анонимных функций, в которых выполняется сопоставление с шаблоном, так и для анонимных функций, которые просто принимают аргумент. (В OCaml есть function и fun как синтаксические удобства для анонимных функций, тогда как в SML есть только fn.)

  • При перечислении конструкторов или сопоставления с образцом не добавляйте | перед первым регистром.

  • && называется andalso, а || называется orelse. (Обратите внимание, что and означает нечто иное.)

  • Нет List.assoc, так что вы должны это сделать.

  • Исключения Not_found не существует, поэтому вы должны его сделать.

  • Используйте fun вместо let rec для рекурсивных функций; в то время как рекурсивные функции могут определяться с помощью val rec, это не поддерживает параметры в левой части =, как в OCaml. Итак, пока вы могли написать

    val rec eval = fn val_vars => fn e => case e of
        Var x => lookup x val_vars
      | Not e' => not (eval val_vars e)
      | And (e1, e2) => eval val_vars e1 andalso eval val_vars e2
      | Or (e1, e2) => eval val_vars e1 orelse eval val_vars e2
    

    это менее эргономично.

1
Simon Shine 22 Окт 2020 в 01:58