-
DisambiguateRecordFields -
- С версии:
-
6.8.1
- Подразумевается расширением:
- Статус:
-
Включено в
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— нет (фактически оно квалифицируется конструктором).