Вариант, рекурсивная функция и вывод типа - PullRequest
2 голосов
/ 22 марта 2011

Я очень новичок в OCaml, но работал все последние два дня, чтобы понять, как его использовать. В последнее время я много чего делал, но что-то мешает мне двигаться вперед.

Я пытаюсь внедрить evalexpr в OCaml. Довольно легко, используя этот язык, вы бы сказали: так я думал, и первое, что я сделал, используя обычные целые, работало нормально. Но сейчас я пытаюсь сделать это, используя свой СОБСТВЕННЫЙ тип и свои собственные функции для решения операций: и, конечно, это не так просто, как я ожидал.

type expr =
  | Number of MyInt.myint
  | Sum of (expr * expr)
  | Sub of (expr * expr)
  | Product of (expr * expr)
  | Divide of (expr * expr)
  | Modulo of (expr * expr)

let rec evalexpr expr = function
  | Number n       -> n
  | Sum (a, b)     -> MyInt.add (evalexpr a) (evalexpr b)
  | Sub (a, b)     -> MyInt.sub (evalexpr a) (evalexpr b)
  | Product (a, b) -> MyInt.mul (evalexpr a) (evalexpr b)
  | Divide (a, b)  -> MyInt.div (evalexpr a) (evalexpr b)
  | Modulo (a, b)  -> MyInt.modulo (evalexpr a) (evalexpr b)

Мне кажется, это нормально ... но компилятор не согласен. Я думаю, что совершенно очевидно, что «(evalexpr a)» имеет тип MyInt.myint, так как это единственное конечное возвращаемое значение, которое может вернуть функция evalexpr: тем не менее, компилятор думает, что его тип - «expr -> MyInt.myint» .

Значит ли это, что он не применяет функцию evalexpr и возвращает саму функцию ?? если так, то какого черта он это сделает? Я просто не могу понять это. И я не могу придумать другого способа сделать то, чего я пытаюсь достичь здесь.

Ответы [ 2 ]

7 голосов
/ 22 марта 2011

Удалите expr из функции evalexpr.

let rec evalexpr = function
    ...

Имея его там, вы заявляете, что функция принимает 2 параметра. Первое будет связано с переменной expr, а второе будет сопоставлено в теле функции. Затем, когда вы пытаетесь вызвать его рекурсивно, вы вызываете evalexpr с одиночными параметрами, в результате чего функции ожидают второй параметр. Тогда, естественно, ваши функции не могут работать с функциями, поэтому возникает ошибка.

2 голосов
/ 22 марта 2011

Хорошо, я думаю, что это должно быть так:

let rec evalexpr = function
  | Number n       -> n
  | Sum (a, b)     -> MyInt.add (evalexpr a) (evalexpr b)
  | Sub (a, b)     -> MyInt.sub (evalexpr a) (evalexpr b)
  | Product (a, b) -> MyInt.mul (evalexpr a) (evalexpr b)
  | Divide (a, b)  -> MyInt.div (evalexpr a) (evalexpr b)
  | Modulo (a, b)  -> MyInt.modulo (evalexpr a) (evalexpr b)

оператор функции уже принимает аргумент за вас, поэтому вы фактически объявили функцию, которая принимает один аргумент и возвращает функцию

...