6.5.6. Field selectors — Glasgow Haskell Compiler 9.10.0.20240426 User's Guide

# 6.5.6. Field selectors

`FieldSelectors`

  Since: | 9.2.1
  Status: | Included in `GHC2024`, `GHC2021`, `Haskell2010`, `Haskell98`

  Make record field selector functions visible in expressions.

By default, the `FieldSelectors` extension is enabled, so defining a record datatype brings a selector function into scope for each field in the record. `NoFieldSelectors` negates this feature, making it possible to:

- declare a top-level binding with the same name as a field, and
- refer to this top-level binding unambiguously in expressions.

Field labels are still usable within record construction, updates and pattern matching.

For example, given a datatype definition

    data Foo = MkFoo { bar :: Int, baz :: String }

The following will be available:

1. the type constructor `Foo`;
2. the data constructor `MkFoo`;
3. the fields `bar` and `baz` for record construction, update, and pattern matching; and
4. the selector functions `bar :: Foo -> Int` and `baz :: Foo -> String`.

If the `NoFieldSelectors` extension is enabled at the datatype definition site, items (1), (2), and (3) will still be available, but (4) will not. Correspondingly, it is permitted to define a top-level binding with the same name as a field, and using this name in an expression unambiguously refers to the non-field. For exmaple, the following is permitted:

    data Foo = MkFoo { bar :: Int, baz :: String }
    bar = ()  -- does not conflict with `bar` field
    baz = bar -- unambiguously refers to `bar` the unit value, not the field

If you have multiple datatypes with the same field name, you need to enable `DuplicateRecordFields` to allow them to be declared simultaneously. It is never permitted for a single module to define multiple top-level bindings with the same name.

The `DisambiguateRecordFields` extension (implied by `DuplicateRecordFields`) is useful in conjunction with `NoFieldSelectors`, because it excludes non-fields from consideration when resolving field names in record construction, update and pattern matching.

## 6.5.6.1. Import and export of selector functions

Under `FieldSelectors`, these modules are equivalent:

    module A (Foo(MkFoo, bar, baz)) where
      data Foo = MkFoo { bar :: Int, baz :: Int }

    module B (Foo(MkFoo, bar), baz) where
      data Foo = MkFoo { bar :: Int, baz :: Int }

Under `NoFieldSelectors`, these two export statements are now different. The first one will export the field `baz`, but not the top-level binding `baz`, while the second one would export the top-level binding `baz` (if one were defined), but not the field `baz`.

Because of this change, using `NoFieldSelectors` and writing out selector functions explicitly is different to using `FieldSelectors`: in the former case the fields and functions must be exported separately. For example, here the selector functions are not exported:

    {-# LANGUAGE NoFieldSelectors #-}
    module M (Foo(MkFoo, bar, baz)) where
      data Foo = MkFoo { bar :: Int, baz :: Int }

      bar (MkFoo x _) = x
      baz (MkFoo _ x) = x

whereas here the selector functions are exported:

    {-# LANGUAGE FieldSelectors #-}
    module M (Foo(MkFoo, bar, baz)) where
      data Foo = MkFoo { bar :: Int, baz :: Int }

Wildcard exports will export the field labels, but will not export a top-level binding that happens to have the same name. In the examples above, exporting `Foo(..)` is (still) equivalent to exporting `Foo(MkFoo, bar, baz)`.