How to disambiguate data family instances with duplicate record fields?
Summary
I have been upgrading from ghc-8.10.7
to ghc-9.2.5
and dealing with the -Wambiguous-fields
warning as it is deprecating:
This will not be supported by -XDuplicateRecordFields in future releases of GHC.
-XOverloadedRecordDot
is very nice for field access. For record updates I've been qualifying field names to avoid the ambiguity.
I found a data family with multiple instances in the same module, each a record with -XDuplicateRecordFields
, and could not find a way to import from this module qualified in order to disambiguate a record update.
Steps to reproduce
See the repo https://github.com/typechecker/data-family-record-dot for these code snippets:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DuplicateRecordFields #-}
module DataFamily where
import Data.Kind
data Choice = A | B
data family Fam :: Choice -> Type
newtype instance Fam A = FamA{ field :: Int }
newtype instance Fam B = FamB{ field :: Bool }
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE RecordWildCards #-}
module RecordUpdate where
import DataFamily (Choice(..))
import qualified DataFamily as WhoIsB (Fam(FamB), Fam(field))
toggleBool :: WhoIsB.Fam B -> WhoIsB.Fam B
toggleBool b@WhoIsB.FamB{..} =
b{ WhoIsB.field = not field}
$ cabal repl
Resolving dependencies...
Build profile: -w ghc-9.4.4 -O1
In order, the following will be built (use -v for more details):
- data-family-record-dot-0.1.0.0 (lib) (first run)
Configuring library for data-family-record-dot-0.1.0.0..
Preprocessing library for data-family-record-dot-0.1.0.0..
GHCi, version 9.4.4: https://www.haskell.org/ghc/ :? for help
[1 of 2] Compiling DataFamily ( src/DataFamily.hs, interpreted )
[2 of 2] Compiling RecordUpdate ( src/RecordUpdate.hs, interpreted )
src/RecordUpdate.hs:7:1: warning: [-Wunused-imports]
The qualified import of ‘Fam(field)’
from module ‘DataFamily’ is redundant
|
7 | import qualified DataFamily as WhoIsB (Fam(FamB), Fam(field))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/RecordUpdate.hs:11:8: warning: [-Wambiguous-fields]
The record update b {WhoIsB.field = not
field} with type DataFamily.R:FamB is ambiguous.
This will not be supported by -XDuplicateRecordFields in future releases of GHC.
|
11 | b{ WhoIsB.field = not field}
| ^^^^^^^^^^^^^^^^^^^^^^^^
Ok, two modules loaded.
Note that if I followed the advice of the first warning and remove the qualified import of Fam(field)
then I get an error.
- import qualified DataFamily as WhoIsB (Fam(FamB), Fam(field))
+ import qualified DataFamily as WhoIsB (Fam(FamB))
src/RecordUpdate.hs:11:8: error:
Not in scope: ‘WhoIsB.field’
Suggested fix:
Perhaps you want to add ‘field’ to the import list in the import of
‘DataFamily’ (src/RecordUpdate.hs:7:1-49).
|
11 | b{ WhoIsB.field = not field}
|
Expected behavior
I'd expect to be able to use a qualified import to disambiguate. Is there a way? A workaround is to move one of the data family instances to another module, side-stepping the duplicate record field altogether, but that has import consequences for other consumers of the module (now two imports when there was one required to import all instances).
Environment
ghc-9.4.4 and ghc-9.2.5 are the same here.