Closed neongreen closed 4 years ago
No workarounds, and its unlikely to compile. Do you use C at many instantiations of f? Is the purpose of C to be some record-like framework? This isn't a case I thought of, and don't have any great suggestions how to handle it.
This is a common (ish) higher-kinded data pattern. It's used e.g. in DB frameworks like beam.
For my usecase, in 90% of cases f ~ Identity
. In fact, C
for me is defined as:
type family C f where
C Identity a = a
C f a = f a
This is why, for instance, I'd be happy with a pragma that lets me say
{-# RECORD_DOT (Foo Identity) #-}
data Foo f = Foo { x :: C f Int }
As a side-note — do you know if I'm going to hit the same problem with -XRecordDots (or whatever it's called) when it becomes a part of GHC?
The HasField defines the necessary instances. I'm not sure what will happen with higher-kinds there. I suspect it might not work, and you'd have to define your own instances by hand - which in this case doesn't look too troublesome.
A pragma wouldn't be unreasonable - or alternatively a pragma that just says ignore Foo and then you can define your own instances for it. I'd happily take a patch, although I'm not actively using this code, so might not get around to actually implementing it myself.
Let's say we add a pragma. Something like:
{- RECORD_DOT FooT Identity -}
data FooT f = FooT ...
I assume this will be hard to add to the preprocessor reliably? So perhaps it should only be in the GHC plugin.
Any bikeshedding re/ how the pragma should look?
Any helpful tips to whoever will take up implementing this?
Not sure how hard it is to add to the preprocessor - not infeasible. Not too fussed about the pragma design itself. A good question would be what will this look like for the version that gets implemented in GHC? Can we be compatible with that? I'm not really sure.
I think that GHC should cope with this out of the box, at least when the concrete type is known?
I feel that if GHC generates instances on the fly, it should be able to generate a HasField "x" (Foo Identity) (C Identity Int)
instance if it knows that f ~ Identity
. But I'm not sure.
Do you know who's in charge of implementing the proposal in GHC?
That bit will be Adam Gundry - but looking at the existing HasField instances in GHC will probably give you a clue what will happen.
but looking at the existing HasField instances in GHC
Oh, good idea! Thanks
Good news: HasField in GHC 8.10 works just fine.
> getField @"x" (Foo 1 :: Foo Identity)
1
The pragma will not help, because type families are not allowed in an HasField
instance head at all. I'm closing this.
Thanks for tracking this down and figuring it out.
Let’s say we have, HKD-style:
C is a type family here.
Derived instances won’t compile:
Are there any workarounds in the preprocessor for this? Maybe the ability to derive instances only for specific instantiations of
f
?