Сопоставление с образцом, F# по сравнению с Erlang

В Erlang Вы поощряетесь не соответствовать шаблонам, которые Вы на самом деле не обрабатываете. Например:

case (anint rem 10) of
    1 -> {ok, 10}
    9 -> {ok, 25}
end;

стиль, который поощряется с другими возможными результатами, приводящими к a badmatch результат. Это согласовывается с, "позволенный это разрушают" философию в Erlang.

С другой стороны, F# выпустил бы "неполное сопоставление с образцом" в эквивалентном коде F#, как здесь.

Вопрос: почему не был бы F# удалять предупреждение, эффективно путем увеличения каждого сопоставления с образцом с оператором, эквивалентным

|_ -> failwith "badmatch"

и используйте, "позволенный это разрушают" философию?

Править: Два интересных ответа до сих пор: любой для предотвращения ошибок, которые, вероятно, если не обрабатывают все случаи алгебраического типа данных; или из-за платформы .NET. Один способ узнать, который должен проверить OCaml. Так, каково поведение по умолчанию в OCaml?

Править: Удалить недоразумение людьми .NET, у которых нет знаний в Erlang. Точка философии Erlang не должна производить плохой код, который всегда отказывает. Позвольте это разрушить средства позволило некоторому другому процессу зафиксировать ошибку. Вместо того, чтобы писать функцию так, чтобы это могло обработать все возможные случаи, позвольте вызывающей стороне (например), обработать тяжелые случаи, которые брошены автоматически. Для тех, которые имеют фон Java, он похож на различие между наличием языка с контролируемыми исключительными ситуациями, которые должны объявить все, что он возможно возвратит за каждым возможным исключением и наличием языка, на котором функции могут повысить исключения, которые явно не объявляются.

14
задан Community 23 May 2017 в 12:34
поделиться

4 ответа

F # (и другие языки с сопоставлением с образцом, такие как Haskell и O'Caml) неявно добавляют регистр, который вызывает исключение.

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

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

В ответ на вашу правку это также предупреждение по умолчанию в O'Caml (и в Haskell с -Wall).

23
ответ дан 1 December 2019 в 06:08
поделиться

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

Таким образом, я думаю, что компилятор имеет смысл предупреждать разработчика. Если вам не нравится такое поведение, вы можете либо добавить универсальный шаблон, который сам генерирует исключение, либо отключить или игнорировать предупреждение.

13
ответ дан 1 December 2019 в 06:08
поделиться

почему бы F # не удалить предупреждение

Интересно, что вы спросите об этом. Незаметное внедрение источников ошибок времени выполнения абсолютно противоречит философии F # и его родственников. Это считается гротескной мерзостью. Это семейство языков полностью посвящено статической проверке в той степени, в которой система типов была в основном разработана для облегчения именно таких видов статических проверок.

Это резкое различие в философии и является причиной того, что F # и Python так редко сравниваются и противопоставляются. Как говорится, «никогда не сойдутся двое».

Итак, каково поведение по умолчанию в OCaml?

То же, что и в F #: полнота и избыточность совпадений шаблонов проверяется во время компиляции, и выдается предупреждение, если совпадение является подозрительным. Идиоматический стиль также тот же: ожидается, что вы напишете свой код так, чтобы эти предупреждения не появлялись.

Это поведение не имеет ничего общего с .NET, и, фактически, эта функциональность (от OCaml) была правильно реализована в F # совсем недавно.

Например, если вы используете шаблон в , позвольте привязке извлечь первый элемент списка, потому что вы знаете, что в списке всегда будет хотя бы один элемент:

let x::_ = myList

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

Например, вы можете представить непустой список в виде кортежа, содержащего начальный и конечный список. Тогда ваше совпадение с шаблоном станет:

let x, _ = myList

Это исчерпывающе, поэтому компилятор доволен и не выдает предупреждения. Этот код не может ошибиться во время выполнения .

Я стал сторонником этой техники еще в 2004 году, когда я провел рефакторинг около 1kLOC коммерческого кода OCaml, который был основным источником ошибок времени выполнения в приложении (даже если они были явными в форме универсального кода). совпадения случаев, которые вызывали исключения). Мой рефакторинг удалил все источники ошибок времени выполнения из большей части кода. Значительно повысилась надежность всего приложения. Более того, мы потратили зря недели на поиск ошибок через отладку, но мой рефакторинг был завершен в течение 2 дней. Так что этот метод действительно приносит дивиденды в реальном мире.

11
ответ дан 1 December 2019 в 06:08
поделиться

OCaml по умолчанию предупреждает о неполных совпадениях. Вы можете отключить его, добавив "p" к флагу "-w". Смысл этих предупреждений в том, что чаще всего (по крайней мере, по моему опыту) они являются признаком ошибки программиста. Особенно когда все ваши шаблоны действительно сложны, как Node (Node (Leaf 4) x) (Node y (Node Empty _)), легко пропустить случай. Когда программист уверен, что не может пойти не так, явное добавление случая | _ -> assert false является недвусмысленным способом указать на это.

GHC по умолчанию отключает эти предупреждения; но вы можете включить их с помощью -fwarn-incomplete-patterns

3
ответ дан 1 December 2019 в 06:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: