Имя поля записи x можно использовать в четырёх контекстах:
- При создании записи:
C{ x = 3 } - При обновлении записи:
r{ x = 4 } - При сопоставлении с образцом записи:
case r of C{ x = value } -> … - Как отдельный селектор записи:
x r
В этих четырёх случаях действуют следующие правила разрешения имён полей:
- Неквалифицированное имя «x» однозначно тогда и только тогда, когда в области видимости есть только одно неквалифицированное «x».
- Квалифицированное имя «M.x» однозначно тогда и только тогда, когда в области видимости есть только одно «M.x».
Эти правила дополняются следующими расширениями:
-
DisambiguateRecordFields: При создании записей и сопоставлении с образцом (C{ x = …}) неквалифицированное имя поляxоднозначно тогда и только тогда, когда конструктор данных (C) содержит полеxи это поле находится в области видимости без квалификатора либо с квалификаторомQ.x, независимо отQ. Аналогично, при создании записей и сопоставлении с образцом квалифицированное имя поляM.xоднозначно тогда и только тогда, когда конструктор данных (C) содержит полеxи это поле находится в области видимости с квалификаторомM.x.При обновлении записей (
r{ x = 3 }) имя поля x однозначно тогда и только тогда, когда в области видимости есть только одно неквалифицированное имя поля x. Аналогично, обновление записи с квалифицированным полемr{ M.x = 3 }однозначно, если только одно имя поля находится в области видимости какM.x. В обоих случаях имена, не являющиеся именами полей, игнорируются. -
DuplicateRecordFields: Это расширение разрешает обновление записей, если ровно один тип содержит все обновляемые поля, даже если согласно двум приведённым выше правилам разрешения имён полей каждое из них по отдельности неоднозначно.Например:
data S = MkS1 { x :: Int, y :: Bool } | MkS2 { x :: Int } data T = MkT1 { x :: Int, z :: Bool } | MkT2 { z :: Bool } f r = r{ x=3, y=True }
Единственный тип данных, у которого полями являются и x, и y, — это S, поэтому имена полей x и y однозначно относятся к типу данных S.
-
NoFieldSelectors: При включённом этом расширении имена селекторов полей в области видимости игнорируются в контексте выражения.Например:
data T = MkT { x :: Int } x :: String x = "Hello" f = x
При NoFieldSelectors выражение x в правой части f относится к x :: String, а не к полю x.