-
DisambiguateRecordFields -
- Since:
-
6.8.1
- Implied by:
- Status:
-
Included in
GHC2024
Позволяет компилятору автоматически выбирать между полями записей с одинаковыми именами (если выбор однозначен).
При построении записей и сопоставлении с шаблонами записей однозначно определяется, к какому полю относится ссылка, даже если в области видимости находятся два разных типа данных с общим именем поля. Например:
module M where
data S = MkS { x :: Int, y :: Bool }
module Foo where
import M
data T = MkT { x :: Int }
ok1 (MkS { x = n }) = n+1 -- Unambiguous
ok2 n = MkT { x = n+1 } -- Unambiguous
bad1 k = k { x = 3 } -- Ambiguous
bad2 k = x k -- Ambiguous
Несмотря на то, что в области видимости есть две x’ы, ясно, что x в шаблоне в определении ok1 может относиться только к полю x типа S. Аналогично для функции ok2. Однако в обновлении записи в bad1 и выборе записи в bad2 неясно, какой из двух типов подразумевается.
Haskell 98 считает все четыре случая неоднозначными, но с расширением DisambiguateRecordFields GHC будет принимать первые два. Правила точно такие же, как и для объявлений экземпляров в Haskell 98, где имена методов в левой части связываний методов в объявлении экземпляра однозначно ссылаются на метод этого класса (при условии, что они вообще находятся в области видимости), даже если в области видимости есть другие переменные с тем же именем. Это уменьшает громоздкость квалифицированных имён, когда вы импортируете две записи из разных модулей, использующих одно и то же имя поля.
Начиная с версии 9.2.1, поля записей в обновлениях разрешаются неоднозначно, игнорируя имена, которые не являются именами полей, в области видимости. Например, следующее принимается с расширением DisambiguateRecordFields:
module Bar where
import M -- imports the field x
x = ()
e r = r { x = 0 } -- unambiguously refers to the field
Некоторые детали:
-
Разрешение неоднозначностей полей можно комбинировать с омонимией (см. Омонимия записей). Например:
module Foo where import M x=True ok3 (MkS { x }) = x+1 -- Uses both disambiguation and punning -
С расширением
DisambiguateRecordFieldsвы можете использовать неквалифицированные имена полей, даже если соответствующий селектор находится в области видимости квалифицированным. Например, предположив тот же модульM, что и в нашем предыдущем примере, это законно:module Foo where import qualified M -- Note qualified ok4 (M.MkS { x = n }) = n+1 -- UnambiguousТак как конструктор
MkSнаходится в области видимости только квалифицированным, вы должны назвать егоM.MkS, но полеxне нужно квалифицировать, даже еслиM.xнаходится в области видимости, ноxнет (по сути, оно квалифицируется конструктором).