![]() I would have loved to have a type bound R <: TemporalAccessor in the type lambda's, but then the compiler throws a NullpointerException (!). The asterisk syntax is identical to what the kind-projector compiler plugin for Scala 2 allows you to write. The underscore syntax will be the official Scala 3 syntax but isn't (yet) enabled without a compiler flag as it would break Scala 2 code which needs to be migrated or cross-compiled. ![]() The type lambda ' => TemporalAccessor => R' can also be written as'TemporalAccessor => _' with scalac flag '-Ykind-projector:underscores', or as 'TemporalAccessor => *' using scalac flag '-Ykind-projector'. Perhaps writing toNelF as an extension method is a bit over the top, but I'd like to put emphasis on the fact that it resembles and replaces Tuple.toList here. There is still a bit of casting going on inside the implementation, reflecting the implementation of Tuple.toList. I guess a future iteration of the Scala 3 compiler could improve on this? Instead, I created my own version (toNelF) that is 'IsMappedBy'-aware, and made it rely on cats' NonEmptyList' (hence also the NonEmptyTuple) too. There exists a method Tuple.toList, but that won't infer the nested function and union types properly as I need them. The 'we know better what the return type is' part is basically the whole point of this exercise. This is because we re-use the more loosely typed Java implementation. Some casting remains necessary inside the implementation, here '.asInstanceOf'. TuplesĮxtension ( dtf: DateTimeFormatter ) The concept of type lambdas is not new either. Which is exactly the return type we want.Īll this tuple/wrapping/unwrapping stuff may be familiar if you have used shapeless before but is also common in Typescript. from (LocalDateTime, OffseDateTime) to LocalDateTime | OffsetDateTime. builds a union type of the tuple elements, so again e.g. (TemporalAccessor => LocalDateTime, TemporalAccessor => OffsetDateTime) to (LocalDateTime, OffsetDateTime). peels off those wrappers, so we go from e.g. tells us each element in the tuple must have the same 'wrapper type', in this case essentially 'TemporalQuery'. This substitution of lambda's into the required SAM interface by the compiler is called SAM conversion, which normally works fine, but apparently doesn't play well with all the inlining happening here. I tried using 'IsMappedBy' directly, but the compiler cannot infer here that 'om(_)' is a valid 'TemporalQuery'. In a way, that type alias does exist: 'TemporalQuery' is a Single Abstract Method (SAM) interface corresponding to 'TemporalAccessor => R'. But hey, I don't like bothering users with one-off type aliases just for usage in a single method. Essentially the same as separately defining 'type TempQuery = TemporalAccessor => R', and then using e.g. => TemporalAccessor => R: a type lambda. Luckily at use-site, using a tuple argument looks very much the same as a vararg argument, so double parentheses are not needed, as can be seen in the example above. So our queries are not a vararg (losing the element-specific generics) but a Tuple (remembering each type precisely). Scala.NonEmptyTuple: a scala.Tuple which cannot be empty. 'inline' helps the compiler (in this case) to know the types at use-site more precisely, similarly to how Kotlin handles reified generics. Extension: this is the new Scala 3 extension method syntax.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |