-
ImplicitPrelude -
- Имплицитно задано:
-
RebindableSyntaxподразумеваетNoImplicitPrelude. - С:
-
6.8.1
Неявно импортирует модуль
Preludeпо умолчанию.Неявный импорт можно уточнить в модуле, явно написав импорт в формате:
import Prelude (foo)
Это позволит импортировать только
fooизPrelude, а не весь модуль, как при неявном импорте.
GHC обычно импортирует для вас модуль Prelude. Если вы предпочитаете, чтобы этого не происходило, используйте опцию -XNoImplicitPrelude. Идея в том, что вы можете импортировать собственный Prelude.
-
RebindableSyntax -
- Подразумевает:
- С:
-
7.0.1
Включает возможность перепривязки различных обычно встроенных операций.
Представьте, что вы импортируете собственный Prelude для определения собственной иерархии числовых классов. Это полностью разрушает цель, если буквальный «1» означает «Prelude.fromInteger 1», что и предусматривает спецификация Haskell Report. Поэтому расширение 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 будет импортирован неявно вместо стандартного 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 разрешает оператору иметь только один аргумент, что, в свою очередь, позволяет вам записывать функцию постфиксным способом.
Расширение не распространяется на левую сторону определений функций; такие функции должны быть определены в префиксной форме.