Spec-Zone.ru › Haskell 9

6.2.10. Синтаксис перепривязки и неявный импорт Prelude

ImplicitPrelude
Имплицитно задано:

RebindableSyntax подразумевает NoImplicitPrelude.

С:

6.8.1

Неявно импортирует модуль Prelude по умолчанию.

Неявный импорт можно уточнить в модуле, явно написав импорт в формате:

import Prelude (foo)

Это позволит импортировать только foo из Prelude, а не весь модуль, как при неявном импорте.

GHC обычно импортирует для вас модуль Prelude. Если вы предпочитаете, чтобы этого не происходило, используйте опцию -XNoImplicitPrelude. Идея в том, что вы можете импортировать собственный Prelude.

RebindableSyntax
Подразумевает:

NoImplicitPrelude

С:

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)», как в числовых шаблонах, так и в выражениях.
  • Условные выражения (например, «if e1 then e2 else e3») означает «ifThenElse e1 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
С:

7.10.1

Статус:

Включен в GHC2024, GHC2021

Разрешает использование постфиксных операторов

Расширение PostfixOperators включает небольшое расширение синтаксиса левых операторных секций, что позволяет определять постфиксные операторы. Расширение заключается в том, что для любого выражения e и оператора (!), левая секция

(e !)

эквивалентна (с точки зрения проверки типов и выполнения) выражению

((!) e)

Строгое толкование Haskell 98 состоит в том, что секция эквивалентна

(\y -> (!) e y)

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

Расширение не распространяется на левую сторону определений функций; такие функции должны быть определены в префиксной форме.

© 2002–2007 The University Court of the University of Glasgow. All rights reserved.
Licensed under the Glasgow Haskell Compiler License.
https://downloads.haskell.org/~ghc/9.12.1/docs/users_guide/exts/rebindable_syntax.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API