2015-04-22 2 views
4

Я часто делаю сопоставление шаблонов в инструкции let, где я знаю форму результата. Понятно, что я не могу ожидать, что компилятор вообще выведет эти знания, но, возможно, существует более идиоматический способ сделать это в сжатой форме.Предупреждение 8: Неполное предупреждение о совпадении шаблонов в заявлении let

В качестве примера, пожалуйста, посмотрите на следующий код:

type foo = A of int | B of string 
let x = (true, A 0) 
let (b, A i) = x in i + 2 

Что правильно предупреждает меня, что результат (_, B _) не соответствует. Возможный способ явно обрабатывает отсутствующий случай, как в:

let (b,i) = match x with 
    | (a, A j) -> (a,j+2) 
    | _ -> failwith "implementation error!" 

Но это затемняет фактический расчет. Есть ли более краткий вариант?

Редактировать: Jeffrey Scofield отметил, что в случае без вложенности явная функция преобразования работает хорошо. Есть ли версия для вложенного соответствия типов?

+2

Обычно безопасный подход заключается в определении 'i', а затем определении' x', поэтому вы уже извлекли 'i' без риска ошибки выполнения; например 'let i = 0 ;; пусть x = (true, A i) ;; i + 2 ;; ' –

ответ

4

Для простых случаев вы можете написать частичную функцию для извлечения значения интереса, аналогичного по духу List.hd.

let int_of_foo = function 
    | A i -> i 
    | _ -> raise (Invalid_argument "int_of_foo") 

let string_of_foo = function 
    | B s -> s 
    | _ -> raise (Invalid_argument "string_of_foo") 

let (_, f) = x in int_of_foo f + 2 

Есть также (не частично) функцию для выступающих пар:

int_of_foo (snd x) + 2 

(я обновил свое использование x, чтобы соответствовать вашему, извините.)

+0

Да, вот почему в примере, который я дал, есть внутри. –

+0

Я не думаю, что это затрудняет ситуацию в этом случае, потому что это легко полностью сопоставить с парой. Но в целом я вижу те же компромиссы в своем кодировании. –

+0

Проблема в том, что более глубокие вложения настолько специфичны, что функция не будет использоваться повторно. Однако незнакомый с кодом человек должен будет найти свое определение. –

6

Если вы уверены, перейдите в нужное дело, и вы используете OCaml 4.02 или новее, вы можете добавить [@@warning "-8"] к вашей декларации.

См. the OCaml manual для получения дополнительной информации об атрибутах.

В предыдущих версиях OCaml вы можете отключить предупреждение относительно всего файла (это зависит от вашего рабочего процесса) или использовать явное сопоставление шаблонов, как описано в ответе Джеффри Скофилда.

Я бы посоветовал «отключить предупреждение по всему файлу», поскольку он будет скрывать другое неполное сопоставление шаблонов, которое может неожиданно нарушить ваш код в настоящем (что легко заметить) ... или где-то в будущем (например, если вы измените тип, с которым вы соглашаетесь в более позднем обновлении).

1

Часто вы можете сделать это без утверждения (т. Е. Проверить свой код во время компиляции), если вместо этого вы используете полиморфный вариант, например.

type foo = [`A of int | `B of string] 
let x = (true, `A 0) 
let (b, `A i) = x in i + 2 
Смежные вопросы