Имя поля записи 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.