Closed MonoidMusician closed 3 years ago
Looks good, but do we need the RowCons
superclass?
It's not strictly necessary, but I think it makes sense as a nice abstraction that saves writing the implied RowCons
, especially for the common case of using Data.Record.get
. Up to you, though! (Data.Record
could always have a separate function for this case if we want to avoid the superclass....)
Wait, the fundeps should probably be -> label typ row
, since there is only one instance ... still learning the nuances here!
No, the fundeps should be row -> label typ
and label typ -> row
. That is, there is a correspondence between singleton rows and pairs of a label and a type.
What you have now says I can guess all three given no information.
I think the difference between the fundeps would be which type classes are mentioned in the error? For row -> label typ, label typ -> row
you'd get no instance found for RowSingleton
, but with -> row label typ
the user would get no instance for either RowToList
or RowCons
- because there's not enough information to satisfy the instance constraints, but this instance is always selected.
Hm.... testing with this function, I see no differences in the type errors with either of the fundeps:
getlabeltype :: forall label typ row. RowSingleton label typ row => RProxy row -> Tuple (SProxy label) (TProxy typ)
getlabeltype _ = Tuple SProxy TProxy
getlabeltype (RProxy :: RProxy ())
Could not match type
Nil
with type
Cons t0 t1 Nil
while solving type class constraint
Type.Row.RowToList ()
(Cons t0 t1 Nil)
while applying a function getlabeltype
of type RowSingleton t0 t1 t2 => RProxy t2 -> Tuple (SProxy t0) (TProxy t1)
to argument RProxy
while inferring the type of getlabeltype RProxy
But I did notice that I needed to export it!
FWIW I've been using a slightly modified RowSingleton
with | -> label typ row
with no problems in some silly lens code (converting between singleton records and variants).
I believe that @LiamGoodacre has said that fundeps in PS are different from Haskell and relate more to a covering set needed for selecting the instance, versus the notion that one variable directly determines the other. Thus I would say that no information is needed to determine the relationship of the three variables, which is given primarily by RowToList
, and confirmed by RowCons
.
@MonoidMusician That example wouldn't show the issue @LiamGoodacre is talking about, but he's right, the errors will be different in some cases.
I think this is a general-purpose operation that can go in with the row operations. Thoughts?
My use case is extracting a named value in tests:
{acopy} `asserteq` 1
can display a nice error message that is guaranteed to match the variable name. There's probably other uses for it, but I think it is nice just because it fills in the semantic gap/limitation ofRowCons
.C.f. https://github.com/purescript/purescript/issues/2809