Подтвердить что ты не робот

Почему это полезное предупреждение в 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 существует разумное предупреждение здесь, когда среди моих исчерпывающих шаблонов каждый аргумент фактически используется хотя бы один раз?

4b9b3361

Ответ 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

Компилятор пытается предположить, что вы используете определенный стиль кодирования. Если вам это не нравится (достаточно справедливо), есть способ избежать проблемы. См. Например:

Как [временно] подавить "определенные, но не используемые" предупреждения?

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