Неустранимая ошибка: исключение Match_failure("main.ml", 8, 15)
Вот мой код:
type 'a tree = Empty | N of 'a * 'a tree * 'a tree
let absolute x =
if x > 0 then x
else -x
let rec node = function
| N(_, Empty, Empty) -> 1
| N(_, g, d) -> 1 + node g + node d
let rec balanced = function
| N(_, Empty, Empty) -> 0
| N(_,g,d) when absolute (node g - node d) > 1 -> 1
| N(_,g,d) when absolute (node g - node d) <= 1 -> balanced g + balanced d
let () = print_int (balanced (N ('x', N ('x', Empty, Empty),
N ('x', N ('x', Empty, Empty), Empty))))
Тогда это говорит мне:
Fatal error: exception Match_failure("main.ml", 8, 15)
Я не понимаю, что это значит, и, похоже, это не указывает на то, откуда произошла моя ошибка.
Кроме того, я получаю следующие предупреждения:
File "main.ml", line 8, characters 15-93:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Empty
File "main.ml", line 12, characters 19-190:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
(N (_, Empty, N (_, _, _))|N (_, N (_, _, _), _)|Empty)
(However, some guarded clause may match this value.)
Как я могу избавиться от этого предупреждения?
Я имею в виду, по моему мнению, это ничего не значит сказать, что я скучаю по делу N(_,_,_)
, но этот случай всегда обрабатывается, так почему компилятор говорит мне, что этот случай не совпадает?
3 ответа
Прежде чем взглянуть на ошибки во время выполнения, лучше сначала взглянуть на выходные данные компилятора (это предупреждения).
У вас есть два предупреждения. Первый:
File "main.ml", line 8, characters 15-93:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Empty
Здесь это говорит нам о том, что ваш шаблон соответствует node
функция не обрабатывает Empty
дело. Просто добавьте | Empty -> 0
в соответствии с вашим шаблоном, и вы должны быть хорошими (кстати, вам не понадобятся неполные Node (_,Empty,Empty)
дело больше).
Теперь ваше второе предупреждение немного сложнее:
File "main.ml", line 12, characters 19-190:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
(N (_, Empty, N (_, _, _))|N (_, N (_, _, _), _)|Empty)
(However, some guarded clause may match this value.)
Здесь говорится, что несколько шаблонов не совпадают, но некоторые значения защищены. И действительно, дело N (_,_,_)
является.
Вы можете показать компилятору, что все N (_,_,_)
обрабатываются путем удаления второго when
пункт (то есть when absolute (node g - node d) <= 1
). Сопоставление с образцом не достигнет этой точки, если это предложение не является истинным, поэтому вы можете быть уверены, что это так. Кроме того, вы убедитесь, что вы не повторяете одно и то же вычисление дважды таким образом. Обратите внимание, что в этом сопоставлении с шаблоном вы также не обрабатывали Empty
дело снова Сделай это.
Теперь давайте посмотрим на ваше исключение. В основном это говорит: "Сопоставление с образцом в строке 8, символ 15 не удался". Это твой node
функция. Где вы были предупреждены, что ваше сопоставление с образцом было неполным. Урок здесь: "Не игнорируйте предупреждения, они не надоедают, они важны".
Предупреждение не так. Вы пропустили случай, и компилятор сгенерировал пример этого случая для вас. Этот случай появляется во время выполнения, и в результате вы получаете совпадение, которое не удается, потому что вы не обрабатываете его.
Другие уже объяснили предупреждения и что они значат. Следуй за этим.
Я просто хочу добавить кое-что о том, где ваш код не работает в данный момент. В сбалансированной функции вы обнаруживаете, что оба левых и правых потомка являются пустыми, и обрабатываете случай, когда оба потомка не пустые правильно. Но что, если только один ребенок пуст? В этом случае вы вычисляете node g
а также node d
, Одним из них является пустой, который вы не рассмотрели в функции узла. В вашем примере есть узлы, в которых только одна сторона пуста, и там происходит сбой.