-
ImplicitPrelude -
- Подразумевается расширением:
-
RebindableSyntaxподразумеваетNoImplicitPrelude. - Начиная с версии:
-
6.8.1
По умолчанию неявно импортировать модуль
Prelude.Неявный импорт можно уточнить в модуле, явно записав импорт следующего вида:
import Prelude (foo)
Вместо всего модуля неявный импорт будет импортировать из
Preludeтолькоfoo.
Обычно GHC импортирует за вас модуль Prelude. Если вы предпочитаете, чтобы этого не происходило, укажите параметр -XNoImplicitPrelude. Идея в том, что тогда вы сможете импортировать собственный Prelude.
-
RebindableSyntax -
- Подразумевает:
- Начиная с версии:
-
7.0.1
Разрешить переназначение ряда обычно встроенных операций.
Предположим, вы импортируете собственный Prelude, чтобы определить собственную иерархию числовых классов. Такой подход теряет смысл, если литерал «1» означает «Prelude.fromInteger 1», как указано в отчёте Haskell. Поэтому расширение RebindableSyntax приводит к тому, что следующие элементы встроенного синтаксиса ссылаются на то, что находится в области видимости, а не на версии из Prelude:
- Целочисленный литерал
368означает «fromInteger (368::Integer)», а не «Prelude.fromInteger (368::Integer)». - Дробные литералы обрабатываются точно так же, за исключением того, что их преобразование —
fromRational (3.68::Rational). - Строковые литералы обрабатываются аналогичным образом, за исключением того, что их преобразование —
fromString ("368"::String). - Для проверки равенства в числовом шаблоне с перегрузкой используется то, что находится в области видимости под именем
(==). - Для операции вычитания и проверки «больше или равно» в шаблонах
n+kиспользуются те, что находятся в области видимости под именами(-)и(>=). - Отрицание (например, «
- (f x)») означает «negate (f x)» как в числовых шаблонах, так и в выражениях. - Условные выражения (например, «
ife1thene2elsee3») означают «ifThenElsee1 e2 e3». Однако выраженияcaseне затрагиваются. - Нотация «do» преобразуется с использованием функций, которые находятся в области видимости под именами
(>>=),(>>)иfail(а не версий из Prelude). Списковые включения,mdo(Рекурсивная do-нотация) и параллельные включения для массивов не затрагиваются. - В нотации стрелок (см. раздел Нотация стрелок) используются функции, которые находятся в области видимости под именами
arr,(>>>),first,app,(|||)иloop. Однако, в отличие от других конструкций, типы этих функций должны очень точно соответствовать типам из Prelude. Детали пока не окончательны; если вы хотите это использовать, спросите! - Нотацию списков, например
[x,y]или[m..n], также можно обрабатывать с помощью переназначаемого синтаксиса, если использовать-XOverloadedLists; см. раздел Перегруженные списки. - Перегруженная метка «
#foo» означает «fromLabel @"foo"», а не «GHC.OverloadedLabels.fromLabel @"foo"» (см. раздел Перегруженные метки).
RebindableSyntax подразумевает NoImplicitPrelude.
Во всех случаях (кроме нотации стрелок) статическая семантика должна соответствовать десахаризованной форме, даже если это кажется неожиданным. Например, статическая семантика литерала 368 в точности совпадает со статической семантикой fromInteger (368::Integer); допустимо, чтобы fromInteger имело любой из следующих типов:
fromInteger :: Integer -> Integer fromInteger :: forall a. Foo a => Integer -> a fromInteger :: Num a => a -> Integer fromInteger :: Integer -> Bool -> Bool
Обратите внимание: это экспериментальная возможность, предусматривающая меньше проверок, чем обычно. Используйте -dcore-lint для проверки типов десахаризованной программы. Если Core Lint не выдаёт ошибок, всё должно быть в порядке.
6.2.10.1. Пользовательские модули Prelude с именем Prelude
Если назвать пользовательский модуль Prelude Prelude и поместить его в файл с именем Prelude.hs, он будет неявно импортирован вместо Prelude по умолчанию.
Вот пример, который компилируется:
$ cat Prelude.hs module Prelude where a = () $ cat B.hs module B where foo = a $ ghc Prelude.hs B.hs [1 of 2] Compiling Prelude ( Prelude.hs, Prelude.o ) [2 of 2] Compiling B ( B.hs, B.o )
Новый Prelude неявно импортируется в B.hs.
Вот пример, который не компилируется:
$ cat Prelude.hs module Prelude where foo = True $ ghc Prelude.hs [1 of 1] Compiling Prelude ( Prelude.hs, Prelude.o ) Prelude.hs:3:7: error: Data constructor not in scope: True
В этом случае исходный модуль Prelude скрывается пользовательским Prelude. Чтобы включить исходный Prelude в пользовательский Prelude, его можно явно импортировать с параметром -XPackageImports и import "base" Prelude.
Явный импорт Prelude подавляет неявный импорт. Это позволяет уточнить неявный импорт:
$ cat Prelude.hs
module Prelude where
a = ()
b = ()
$ cat B.hs
module B where
import Prelude (b)
-- a is now not in scope, there is no implicit Prelude import
foo = a
qux = b
$ ghc Prelude.hs B.hs
[1 of 2] Compiling Prelude ( Prelude.hs, Prelude.o )
[2 of 2] Compiling B ( B.hs, B.o )
B.hs:5:7: error: [GHC-88464]
Variable not in scope: a
Suggested fix:
Add 'a' to the import list in the import of 'Prelude'
(at B.hs:3:1-18).
|
5 | foo = a
|
Примечание
Импорт модуля с именем Prelude с расширением PackageImports не влияет на неявный импорт Prelude:
> cat Prelude.hs
module Prelude where
a = ()
> cat B.hs
{-# LANGUAGE PackageImports #-}
module B where
import "base" Prelude
-- This definition comes from the implicit prelude import
foo = a
-- These definitions come from the package import
baz :: Int -> Int -> Int
baz = (+)
> ghc B.hs
[1 of 2] Compiling Prelude ( Prelude.hs, Prelude.o )
[2 of 2] Compiling B ( B.hs, B.o )
Чтобы использовать пакетные импорты, следует явно отключить импорт неявного модуля prelude, включив расширение NoImplicitPrelude.
6.2.10.2. Что не затрагивается расширением RebindableSyntax
RebindableSyntax не применяется к коду, сгенерированному из предложения или объявления deriving. Чтобы понять почему, рассмотрим следующий код:
{-# LANGUAGE RebindableSyntax, OverloadedStrings #-}
newtype Text = Text String
fromString :: String -> Text
fromString = Text
data Foo = Foo deriving Show
При этом будет сгенерирован код, эквивалентный следующему:
instance Show Foo where showsPrec _ Foo = showString "Foo"
Но поскольку включены расширения RebindableSyntax и OverloadedStrings, строковый литерал "Foo" теперь будет иметь тип Text, а не String, который не принимает showString! Из-за этого сгенерированный экземпляр Show не пройдёт проверку типов. Трудно представить ситуацию, в которой поведение RebindableSyntax в производном коде было бы желательным, поэтому GHC полностью игнорирует RebindableSyntax при проверке производного кода.
6.2.11. Постфиксные операторы
-
PostfixOperators -
Разрешает использование постфиксных операторов
Расширение PostfixOperators добавляет небольшое расширение к синтаксису левых сечений операторов, позволяя определять постфиксные операторы. Суть расширения такова: для любого выражения e и оператора (!) левое сечение
(e !)
эквивалентно (с точки зрения как проверки типов, так и выполнения) выражению
((!) e)
В строгой интерпретации Haskell 98 сечение эквивалентно
(\y -> (!) e y)
То есть оператор должен быть функцией от двух аргументов. GHC позволяет ему принимать только один аргумент, что, в свою очередь, позволяет записывать функцию в постфиксной форме.
Расширение не распространяется на левую часть определения функции; такую функцию необходимо определять в префиксной форме.