-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
No way to differentiate NamedTuple from other types #22422
Comments
The fact that we are unable to do that is a direct consequence of the semantics of opaque type aliases. Given that named tuples are opaque type aliases, we cannot distinguish them that way, since they are not provably disjoint from anything else. Could you elaborate on why you would need this? You said:
That sounds a lot like the type-level equivalent of "arbitrary-depth flattening of lists". IIUC I could write the same idea of deep structural equivalence of lists this way: def deepSameListShape(x: Any, y: Any): Boolean = (x, y) match {
case (xHead :: xTail, yHead :: yTail) =>
deepSameListShape(xHead, yHead) && deepSameListShape(xTail, yTail)
case (Nil, _ :: _) | (_ :: _, Nil) =>
false
case _ =>
true // neither are lists, or both are Nil
} That's usually considered a big code smell. The user of Dispatching on whether an arbitrary type is a named tuple or not seems very similar in spirit to the above. Based on that, it seems like a code smell as well. |
@sjrd the use case is to say that Another one is |
Is the argument to So, I guess you're using named tuples for their type syntax only, without using value? |
its using Selectable Fields - and so there would be some operation using an evidence parameter that the substructure proof exists between the types to do a "Safe cast" |
I imagine the same sort of thing could be used to convert between two similar named tuples - e.g. to swap order - or drop/add fields |
Usually for this sort of thing, you would statically know the expected depth of tupling. And so you wouldn't need to "dynamically" (at the type-level) test whether a type is a named tuple or not. Likewise with lists of lists. You would statically know whether you need to do |
but for derivation you dont know, it comes from the structure of types, if you can only inspect 1 level deep that is very limited. I guess you are suggesting for this context example, basically each level should then be boxed in a new Context - but to construct the initial context from e.g. a raw arbitrarily nested named tuple value then you need to traverse the type - perhaps this would work in the way such that you NamedTuple.Map each level starting from the outside, but as you enter the inner levels maybe this would not reduce, id have to try |
Given that if not a general subtyping compiletime op, then an alternative mode to match types that is static dispatch? (is that inline match)? scala> summon[scala.util.NotGiven[Int <:< NamedTuple.AnyNamedTuple]]
val res1: scala.util.NotGiven[Nothing] = scala.util.NotGiven@23eb7e28 |
Assume you have a type level algorithm over named tuples that needs to recurse when the value type is a named tuple, otherwise do something else. (e.g. check a named tuple is substructually equivalent to another)
Currently there isn't a way to do that because you cannot differentiate named tuple from other types
Compiler version
3.6.3
Minimized code
Perhaps there is a better way, but for simplicity you can not use match types on their own because the upper bound of AnyNamedTuple is Any.
Output
Expectation
the standard library could have a way to determine if a type is a match type or not, perhaps a primitive compile-time op?
Another trick I wanted to try was if
NamedTuple.From[T]
would reduce or not, but again this isnt useful becauseNamedTuple.From[(foo: Int)]
matchesNamedTuple.From[t]
and alsoNamedTuple[ns, vs]
so cant be distinguished from a reduced or non-reduced formThe text was updated successfully, but these errors were encountered: