Open arybczak opened 3 years ago
Thank you for the request! However, this one looks like an optic
-library specific feature, as that #name
is not directly related to name
outside of the library.
If you think this one is more general than optic
, could you elaborate why do you think so?
However, this one looks like an optic-library specific feature
That is unfortunately true, it's specific to optics
. generic-lens
offers something similar for lens
-compatible optics, but it uses different types.
It's just that with tags-based navigation jumping to definition using #name
works (admittedly somewhat by accident since #
is not considered part of a symbol and dropped), while with HLS it doesn't.
It's quite unfortunate, because using labels as field lenses is the only way to handle fields without prefix in a sane manner in Haskell, so it would be great if it did
I can't think of a way to make this nice without a special case. The IsLabel
instance really is in optics
, and there's no obvious way to tell that it's "really" associated with one of the types that appears in the instance head, let alone a particular field of that type.
And even if we had a special case, it would sometimes be wrong. Where should we jump to if you write a function that's generic over all LabelOptic "name" k s t a b
? You could still write #name
, but where would it go? The only reasonable thing that makes sense in all contexts is the definition of fromLabel
... but that's not what you want.
It's just that with tags-based navigation jumping to definition using #name works (admittedly somewhat by accident since # is not considered part of a symbol and dropped), while with HLS it doesn't.
I think "it works in my existing system due to a bug" is not a good argument for replicating that ;) This would of course go horribly wrong for any other use of OverloadedLabels
. Or with multiple records with "name" fields, etc.
With GHC 9.0 we can implement "go to instance definition", like this. That won't take you to the record field, but it would take you to both the IsLabel
instance and the Generic
instance for your specific record.
I can't think of a way to make this nice without a special case.
Right, I don't think it's possible.
The only reasonable thing that makes sense in all contexts is the definition of fromLabel... but that's not what you want.
Indeed, it's quite unfortunate.
@michaelpj Your points are valid, all I'm pointing out is that it's unfortunate that it doesn't work. Perhaps if optics
was more prevalent in the ecosystem and the go to solution for labels-as-lenses, making it a special case would make more sense.
Perhaps we should wait for that to happen (assuming that it does) and re-evaluate. I'd obviously like that to happen sooner as an author and a user, but oh well :)
That won't take you to the record field, but it would take you to both the IsLabel instance and the Generic instance for your specific record.
@wz1000 Would it take me to a Generic
instance definition for the type (which is almost always below field definitions)? If that was an option, it would be great.
@wz1000 Would it take me to a Generic instance definition for the type (which is almost always below field definitions)? If that was an option, it would be great.
Yes it would.
optics-core
supports using overloaded labels as field lenses (and constructor prisms) for types with aGeneric
instance since 0.4.Consider the following module (full project for ease of reproducibility is here).
With
name
in the definition ofgetName_gotoWorks
jumping to the definition works fine. However, trying to do the same using#name
withingetName_gotoDoesntWork
doesn't.Would it be possible to add a support for this? On hover the term
#name
is a dictionary forIsLabel "name" (Optic' A_Lens NoIx (User p) String)
, so in principle it's possible to go to the field definition as all the information is there.A somewhat more complicated case is in
setFields_ambiguousMiddleType
: hovering over#name
there shows justIsLabel
, presumably due to undetermined phantom type variable (since getting rid of the type variable show the full type) :thinking: Hovering over#age
gives all the dictionary info (IsLabel "age" (Optic A_Lens NoIx (User Any) (User p) Int Int
).Output of
haskell-language-server --probe-tools
: