GHC поддерживает несколько прагм, или инструкций для компилятора, размещаемых в исходном коде. Прагмы обычно не влияют на смысл программы, но могут повлиять на эффективность сгенерированного кода.
Все прагмы имеют вид {-# word ... #-} , где ⟨слово⟩ указывает тип прагмы, и за ним необязательно следует информация, специфичная для этого типа прагмы. Регистр в ⟨слове⟩ игнорируется. Различные значения для ⟨слово⟩, которые понимает GHC, описаны в следующих разделах; любая встреченная прагма с нераспознанным ⟨словом⟩ игнорируется.
Определенные прагмы являются прагмами заголовка файла:
- Прагма заголовка файла должна предшествовать ключевому слову
moduleв файле. - Можно использовать любое количество прагм заголовка файла, и им могут предшествовать или следовать комментарии.
- Прагмы заголовка файла читаются один раз, перед предварительной обработкой файла (например, с помощью cpp).
- Прагмы заголовка файла:
{-# LANGUAGE #-},{-# OPTIONS_GHC #-}, и{-# INCLUDE #-}.
6.20.1. LANGUAGE прагма
-
{-# LANGUAGE ⟨ext⟩, ⟨ext⟩, ... #-} -
- Где:
-
заголовок файла
Включить или отключить набор расширений языка.
Прагма LANGUAGE позволяет включить расширения языка портативным способом. Предполагается, что все компиляторы Haskell поддерживают прагму LANGUAGE с одинаковым синтаксисом, хотя, конечно, не все расширения поддерживаются всеми компиляторами. Прагму LANGUAGE следует использовать вместо OPTIONS_GHC, если это возможно.
Например, для включения FFI и предварительной обработки с CPP:
{-# LANGUAGE ForeignFunctionInterface, CPP #-}
LANGUAGE — это прагма заголовка файла (см. Прагмы).
Каждое расширение языка также может быть преобразовано в командную строку, добавив префикс «-X»; например, -XForeignFunctionInterface. (Аналогично, все флаги «-X» можно записать как прагмы LANGUAGE).
Список всех поддерживаемых расширений языка можно получить, вызвав ghc --supported-extensions (см. --supported-extensions).
Любое расширение типа Extension , определённое в Language.Haskell.Extension, может быть использовано. GHC сообщит об ошибке, если любое из запрошенных расширений не поддерживается.
6.20.2. OPTIONS_GHC прагма
-
{-# OPTIONS_GHC ⟨flags⟩ #-} -
- Где:
-
заголовок файла
Прагма OPTIONS_GHC используется для указания дополнительных параметров, которые передаются компилятору при компиляции данного исходного файла. Подробнее см. Параметры командной строки в исходных файлах.
Предыдущие версии GHC принимали OPTIONS вместо OPTIONS_GHC, но это теперь устаревшая форма.
OPTIONS_GHC — это прагма заголовка файла (см. Прагмы).
6.20.3. INCLUDE прагма
Прагма INCLUDE раньше была необходима для указания заголовочных файлов, которые должны быть включены при использовании FFI и компиляции через C. Она больше не требуется для GHC, но принимается (и игнорируется) для совместимости с другими компиляторами.
6.20.4. WARNING и DEPRECATED прагмы
-
{-# WARNING #-} -
- Где:
-
имя объявления или модуля
Прагма
WARNINGпозволяет прикрепить произвольное предупреждение к определённой функции, классу, типу, полю экспорта или модулю.
-
{-# DEPRECATED #-} -
- Где:
-
имя объявления или модуля
Прагма
DEPRECATEDпозволяет указать, что определённая функция, класс, тип, экспорт или модуль устарел.
Существует три способа использования этих прагм.
-
Можно работать с целым модулем:
module Wibble {-# DEPRECATED "Use Wobble instead" #-} where ...Или:
module Wibble {-# WARNING "This is an unstable interface." #-} where ...При компиляции любого модуля, импортирующего
Wibble, GHC выведет указанное сообщение. -
Можно прикрепить предупреждение к функции, классу, типу или конструктору данных с помощью следующих объявлений верхнего уровня:
{-# DEPRECATED f, C, T "Don't use these" #-} {-# WARNING unsafePerformIO "This is unsafe; I hope you know what you're doing" #-}При компиляции любого модуля, импортирующего и использующего указанные сущности, GHC выведет указанное сообщение.
Вы можете прикрепить предупреждение только к сущностям, объявленным на верхнем уровне в компилируемом модуле, и вы можете использовать только неквалифицированные имена в списке сущностей. Заглавное имя, например,
Tотносится либо к конструктору типаTлибо к конструктору данныхT, или к обоим, если оба находятся в области видимости. Если оба находятся в области видимости, в настоящее время нет способа указать один без другого (ср. фиксы Инфиксные конструкторы типов, классы и переменные типов). -
Можно добавить предупреждение к экземпляру (включая производные экземпляры):
instance {-# DEPRECATED "Don't use" #-} Show T1 where { .. } instance {-# WARNING "Don't use either" #-} Show G1 where { .. } deriving instance {-# DEPRECATED "to be removed" #-} Eq T2 deriving instance {-# WARNING "to be removed as well" #-} Eq G2Это приведет к выводу предупреждений всякий раз, когда такие экземпляры используются для решения ограничения. Например:
foo = show (MkT1 :: T1) -- warning: uses "instance Show T1" bar :: forall a. Eq a => a -> Bool bar x = x == x baz :: T2 -> Bool baz = bar -- warning: uses "instance Eq T2" quux :: Eq T2 => T2 -> Bool quux = bar -- no warning: does not use "instance Eq T2"
Как и в других механизмах устаревания, обратите внимание, что предупреждения не будут выводиться для использования этих экземпляров в модуле, в котором они определены.
-
Наконец, можно добавить предупреждение к полю экспорта, будь то обычный экспорт:
module Wibble ( {-# DEPRECATED "Do not use this type" #-} T, {-# WARNING "This is a hacky function" #-} f ) where ...Или повторный экспорт импорта из другого модуля:
module Wibble ( {-# DEPRECATED "Import this function from A instead" #-} g ) where import AИли повторный экспорт целого модуля:
module Wibble ( {-# DEPRECATED "This declaration has been moved to B instead" #-} module B ) where import BПри компиляции любого модуля, импортирующего и использующего указанные сущности, GHC выведет указанное сообщение.
Сущность будет предупреждена только в том случае, если все её экспортные элементы устарели:
module Wibble ( {-# WARNING "This would not be warned about" #-} g, module A ) import A (g)Если включён флаг :ghc-flag:
-Wincomplete-export-warnings, такие случаи предупреждаются.Кроме того, все объявления предупреждений одного имени должны быть предупреждены с той же прагмой и сообщением:
module Wibble ( {-# WARNING "This would throw an error" #-} T(T1), {-# WARNING "Because the warning messages differ for T" #-} T, ) ...
Также обратите внимание, что аргумент к DEPRECATED и WARNING также может быть списком строк, в этом случае строки будут отображаться на отдельных строках в результирующем сообщении о предупреждении,
{-# DEPRECATED foo, bar ["Don't use these", "Use gar instead"] #-}
Предупреждения и устаревания не сообщаются для (a) использования в определяющем модуле, (b) определения метода в экземпляре класса, (c) неквалифицированного использования сущности, импортированной через различные модули, когда не все они предупреждены, и (d) использования в списке экспорта (за исключением предупреждений экспорта). Последнее уменьшает ложные жалобы в библиотеке, в которой один модуль собирает и повторно экспортирует экспорт нескольких других.
Прагма WARNING (но не прагма DEPRECATED ) может необязательно указать категорию предупреждения как строковую литерал после ключевого слова in . Это влияет на флаг, используемый для подавления предупреждения. Примеры выше не указывают категорию, поэтому применяется категория по умолчанию deprecations , и они могут быть подавлены с помощью флага -Wno-deprecations (и его синонима -Wno-warnings-deprecations).
Если категория указана, предупреждение можно подавить с помощью флага -Wno-x-⟨category⟩, например, предупреждения из следующей прагмы можно подавить с помощью -Wno-x-partial:
{-# WARNING in "x-partial" head "This function is partial..." #-}
В качестве альтернативы, предупреждения из всех прагм WARNING и DEPRECATED независимо от категории можно подавить с помощью -Wno-extended-warnings.
Когда устаревшее имя появляется как в пространстве имён значений, так и в пространстве имён типов (т.е. происходит омонимия) прагмы WARNING и DEPRECATED повлияют на оба:
{-# LANGUAGE PatternSynonyms #-}
data D = MkD
pattern D = MkD
{-# DEPRECATED D "This will deprecate both the type D and the pattern synonym D" #-}
Можно указать пространство имён имени, о котором нужно предупредить или которое устарело, с помощью спецификаторов type и data , но для этого необходимо включить ExplicitNamespaces:
{-# LANGUAGE PatternSynonyms #-}
data D = MkD
pattern D = MkD
{-# DEPRECATED data D "This will deprecate only the pattern synonym D" #-}
{-# DEPRECATED type D "This will deprecate only the type D" #-}