Опубликован: 19.09.2008 | Уровень: специалист | Доступ: платный
Лекция 6:

Модули

< Лекция 5 || Лекция 6: 123 || Лекция 7 >

5.3. Объявления импорта

impdecl \to import [qualified] modid [as modid] [impspec]
| (пустое объявление)
impspec \to ( import1 , ... , importn [ , ] ) (n <- 0)
| hiding ( import1 , ... , importn [ , ] ) (n <- 0)
import \to var
| tycon [ (..) | ( cname1 , ... , cnamen )] (n <- 0)
| tycls [(..) | ( var1 , ... , varn )] (n <- 0)
cname \to var | con

Переводы:

объявление-импорта \to import [qualified] идентификатор-модуля [as идентификатор-модуля] [спецификатор-импорта]
| (пустое объявление)
спецификатор-импорта \to ( импорт1 , ... , импортn [ , ] ) (n <- 0)
| hiding ( импорт1 , ... , импортn [ , ] ) (n <- 0)
импорт \to переменная
| конструктор-типа [ (..) | ( c-имя1 , ... , c-имяn )] (n <- 0)
| класс-типа [(..) | ( переменная1 , ... , переменнаяn )] (n <- 0)
c-имя \to переменная | конструктор

Сущности, экспортируемые модулем, можно ввести в область видимости другого модуля посредством объявления import в начале модуля. В объявлении import указывается импортируемый модуль и необязательно задаются импортируемые сущности. Один модуль можно импортировать с помощью более чем одного объявления import. Импортированные имена служат в качестве объявлений верхнего уровня: их область видимости простирается над всем телом модуля, но может быть сокрыта локальными связываниями имен отличного от верхнего уровня.

Влияние многократных объявлений import строго кумулятивно: сущность находится в области видимости, если она импортирована посредством любого из объявлений import в модуле. Порядок объявлений импорта не существенен.

С точки зрения лексики, каждый из терминальных символов "as", "qualified" и "hiding" является varid (идентификатором-переменной), а не reservedid (зарезервированным-идентификатором). Они имеют специальное значение только в контексте объявления import ; их также можно использовать в качестве переменных.

5.3.1. Что такое импортирование

Какие точно сущности должны быть импортированы, можно задать одним из следующих трех способов:

  1. Импортируемые сущности можно задать явно, перечислив их в круглых скобках. Элементы списка имеют ту же форму, что элементы в списках экспорта, за исключением того, что нельзя использовать квалификаторы и нельзя использовать сущность 'module modid'. Когда форма (..) импорта используется для типа или класса, (..) ссылается на все конструкторы, методы или имена полей, экспортированные из модуля.

    В списке должны быть указаны только сущности, экспортированные импортируемым модулем. Список может быть пуст, в этом случае ничто, кроме экземпляров, не будет импортировано.

  2. Сущности могут быть исключены посредством использования формы hiding(import1 , ... , importn ) , которая указывает, что все объекты, экспортированные названным модулем, должны быть импортированы, за исключением указанных в списке. Конструкторы данных можно указать непосредственно в списках hiding без использования в префиксе связанного с ним типа. Таким образом, в
    import M hiding (C)

    любой конструктор, класс, или тип, названный C, исключен. Напротив, используя C в списке импорта, вы укажете лишь класс или тип.

    Будет ошибкой указать в списке hiding сущность, которая на самом деле не экспортируется импортируемым модулем.

  3. Наконец, если impspec пропущен, то все сущности, экспортируемые указанным модулем, будут импортированы.

5.3.2. Импортирование с использованием квалификаторов

Для каждой сущности, импортируемой в соответствии с правилами раздела "5.3.1" , расширяется окружение верхнего уровня. Если объявление импорта использует ключевое слово qualified, то только квалифицированное имя сущности вводится в область видимости. Если ключевое слово qualified опущено, то оба имени: квалифицированное и неквалифицированное имя сущности - вводятся в область видимости. В разделе "5.5.1" квалифицированные имена описаны более подробно.

Квалификатор импортированного имени является именем импортированного модуля или локальным синонимом, заданным с помощью инструкции as (раздел "5.3.3" ) в инструкции import. Следовательно, квалификатор необязательно является именем модуля, в котором первоначально была объявлена сущность.

Возможность исключить неквалифицированные имена позволяет программисту осуществлять полное управление пространством неквалифицированных имен: локально определенная сущность может совместно использовать то же имя, что и импортируемая сущность с квалифицированным именем:

module Ring where
  import qualified Prelude    - Все имена из Prelude должны быть квалифицированными
  import List( nub )

  l1 + l2 = l1 Prelude.++ l2  - Этот + отличается от + в Prelude
  l1 * l2 = nub (l1 + l2)     - Эта * отличается от * в Prelude

  succ = (Prelude.+ 1)

5.3.3. Локальные синонимы

Импортированным модулям можно присвоить локальный синоним в модуле, который осуществляет импортирование, для этого используется инструкция as. Например, в

import qualified VeryLongModuleName as C

к импортированным сущностям можно обращаться, используя в качестве квалификатора 'C.' вместо 'VeryLongModuleName.'. Это также позволяет другому модулю быть замененным на VeryLongModuleName без изменения квалификаторов, используемых для импортированного модуля. Более чем один модуль в области видимости может использовать тот же самый квалификатор, при условии, что все имена по-прежнему могут быть однозначно разрешены. Например:

module M where
    import qualified Foo as A
    import qualified Baz as A
    x = A.f

Этот модуль является правильным только при условии, что и Foo, и Baz не экспортируют f.

Инструкцию as можно также использовать в инструкции import без qualified:

import Foo as A(f)

Это объявление вводит в область видимости f и A.f.

5.3.4. Примеры

Для того чтобы разъяснить вышеупомянутые правила импорта, предположим, что модуль A экспортирует x и y. Тогда эта таблица показывает, какие имена будут введены в область видимости с помощью заданного объявления импорта:

Объявление импорта Имена, введенные в область видимости
import A x, y, A.x, A.y
import A() (ничего)
import A(x) x, A.x
import qualified A A.x, A.y
import qualified A() (ничего)
import qualified A(x) A.x
import A hiding () x, y, A.x, A.y
import A hiding (x) y, A.y
import qualified A hiding () .x, A.y
import qualified A hiding (x) A.y
import A as B x, y, B.x, B.y
import A as B(x) x, B.x
import qualified A as B B.x, B.y

Во всех случаях все объявления экземпляров в области видимости в модуле A будут импортированы (раздел "5.4" ).

< Лекция 5 || Лекция 6: 123 || Лекция 7 >
KroshkaRu KroshkaRu
KroshkaRu KroshkaRu
Россия, Петерубрг, СПБ-ГПУ, 1998
Петр Бондареко
Петр Бондареко
Россия