Почему это полезное предупреждение в Haskell при сопоставлении шаблонов? "Определено, но не используется"
При определении нескольких совпадений шаблонов для функции, например, следующим образом:
1: takeTree 0 tree = Leaf
2: takeTree levels (Leaf) = Leaf
3: takeTree levels (Branch value left right) = Branch value (takeTree...
Я получаю два предупреждения в частности:
Source.hs: 1: Предупреждение: определено, но не используется: `tree '
Source.hs: 2: Предупреждение: определено, но не используется: `levels '
Я не сразу убежден, что это полезные предупреждения. Если бы мой код был вместо:
1: takeTree 0 _ = Leaf
2: takeTree _ (Leaf) = Leaf
3: takeTree levels (Branch value left right) = Branch value (takeTree...
который исправляет предупреждения, теперь я считаю, что это гораздо менее удобочитаемо, и запутывает семантику того, что я ожидаю в качестве входных значений.
Почему Defined but not used
существует разумное предупреждение здесь, когда среди моих исчерпывающих шаблонов каждый аргумент фактически используется хотя бы один раз?
Ответы
Ответ 1
Я сделал ошибки кодирования, которые были отмечены этим предупреждением. Упрощенный пример:
fun x xs = go xs
where
go [] = ...
go (y:xs') = f y (go xs)
Рекурсивный вызов должен иметь xs'
как аргумент, конечно, и предупреждение "определено, но не используется" поймает это. Для меня это стоит неудобства использования _ для неиспользуемых совпадений.
Компилятор не может угадать ваши намерения, а тот факт, что вы использовали аргумент в другом совпадении, не означает, что вы не хотели использовать его в матче, генерирующем предупреждение. В конце концов, вы могли бы использовать tree
, поэтому предупреждение о том, что вы этого не сделали, разумно.
См. также ответ Бена: вы можете использовать _name
для использования имени, но все же подавлять предупреждение.
Ответ 2
Предположение, что если что-то было достаточно важным, чтобы назвать его, должно быть достаточно важным, чтобы использовать разумно во многих стилях кодирования.
Но вы можете иметь свой торт и съесть его тоже:
takeTree 0 _tree = Leaf
takeTree _levels (Leaf) = Leaf
takeTree levels (Branch value left right) = Branch value (takeTree...
Ведущее подчеркивание в имени сигнализирует и человеческому читателю и компилятору, что имя не предназначено для использования в этом уравнении, но имя длиннее, чем одно подчеркивание, все еще может передавать больше значения для человека.
Ответ 3
Компилятор пытается предположить, что вы используете определенный стиль кодирования. Если вам это не нравится (достаточно справедливо), есть способ избежать проблемы. См. Например:
Как [временно] подавить "определенные, но не используемые" предупреждения?
Что касается существа дела (независимо от того, является ли это полезным предупреждением): недостаток наименования ваших переменных в таких ситуациях заключается в том, что они имеют смысл, чтобы имена были значимыми для компилятора, когда они не являются. Поверхность, как вы правильно указываете, заключается в том, что они имеют смысл для людей. В принципе есть компромисс, и это довольно субъективно. Важно то, что вы можете получить желаемое поведение, если хотите.