Является ли использование имен шаблонов, начинающихся с "_" (подчеркивание) для игнорируемых результатов, документированных/поощренных/переносимых?

Скажем, я хочу разветкить поток в блоке do -notation, но мне не нужен идентификатор потока. Если я напишу

forkIO action

Предупреждение о проблемах GHC

Предупреждение: оператор do -notation отменил результат типа ThreadId. Подавите это предупреждение, сказав

_ <- forkOS action

Это хорошая идея, поскольку я хочу показать, что программа отбрасывает какой-то результат. Однако таким образом не будет видно, что отбрасывается. Я мог написать

threadId <- forkIO action

но тогда мы скрываем тот факт, что мы не будем использовать ThreadId где угодно, и GHC правильно предупреждает

Предупреждение: определено, но не используется: ThreadId

Кажется, что подчеркивание подчеркивания решает обе проблемы:

_threadId <- forkIO action

Мои вопросы: Используется ли переменная, начинающаяся с подчеркивания в соответствии с спецификацией языка Haskell? Насколько портативен он? Это где-то задокументировано? Рекомендуется ли для подобных случаев документировать, что результат игнорируется?

Ответы

Ответ 1

Да. В разделе раздела 2.4 спецификации 2010 года говорится:

Подчеркивание, _, рассматривается как строчная буква и может происходить везде, где может быть строчная буква.

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

Однако _ сам по себе является зарезервированным идентификатором, который используется в качестве шаблона в виде wild card.

... поэтому вы не можете использовать внешние шаблоны _, поэтому не можете использовать это значение.

Составителям, которые предлагают предупреждения для неиспользуемых идентификаторов, рекомендуется подавлять такие предупреждения для идентификаторов, начинающихся с подчеркивания. Это позволяет программистам использовать _foo для параметра, который, как они ожидают, не используется.

Итак, _threadId - это обычный идентификатор, который вы можете использовать в другом месте, но не следует предупреждать, если его выбросить.

(Точно такой же текст содержится в отчете Haskell 98.)


Примеры:

main = do
     _two <- return 2
     print _two       -- works

компилирует и печатает 2 в соответствии со спецификацией и

main = do
    _two <- return 2
    print 3           -- no warnings, but oops, didn't use _two

компилируется без предупреждения в соответствии со спецификацией и

main = do
    _ <- return 2
    print _        -- syntax error: _ used as identifier

является синтаксической ошибкой в ​​соответствии со спецификацией.