Why DuplicateRecordFields cannot have type inference?
Asked Answered
S

1

8

Related post: How to disambiguate selector function?

https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/DuplicateRecordFields

However, we do not infer the type of the argument to determine the datatype, or have any way of deferring the choice to the constraint solver.

It's actually annoying that this feature is not implemented. I tried to look up multiple sources but I could not find a reason why they decide not to infer types.

Does anyone know a good reason for this? Is it because of a limitation of the current type system?

Specialize answered 7/12, 2016 at 2:11 Comment(2)
Can this be done in future release of ghc at all?Specialize
Presumably that they couldn't find a way to make it work.Wickliffe
Z
11

You will be interested in OverloadedRecordFields which is still being implemented.


The current implementation is intentionally crippled, so as to not introduce too much new stuff all at once. Inferring the record projection types turns out to open a nasty can of worms (which the aforementioned extension addresses).

Consider the following GHCi interaction

ghci> data Record1 = Record1 { field :: Int }
ghci> data Record2 = Record2 { field :: Bool }
ghci> :t field

What should the type of field be now? Somehow, we need a way to capture the notion of "any record with a field called field". To this end, OverloadedRecordFields introduces a new built-in type class

The new module GHC.Records defines the following:

class HasField (x :: k) r a | x r -> a where
  getField :: r -> a

A HasField x r a constraint represents the fact that x is a field of type a belonging to a record type r. The getField method gives the record selector function.

Then, from our example above, it is as if the following instances were magically generated by GHC (in fact that is not actually what will happen, but it is a good first approximation).

instance HasField "field" Record1 Int where
  getField (Record1 f) = f

instance HasField "field" Record2 Bool where
  getField (Record2 f) = f

If you are interested, I recommend reading the proposal. The other feature I haven't mentioned is the IsLabel class. Once all of this is implemented (and some more for updating records) I look forward to being able to get my lenses for free (so I can stop declaring field names starting with an underscore and enabling TemplateHaskell for makeLenses).

Zing answered 7/12, 2016 at 3:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.