From beea7fb1334dacf94e99b68c65a4f6b2b82a86a4 Mon Sep 17 00:00:00 2001 From: Scala Improvement Bot Date: Sat, 20 Jan 2024 00:21:31 +0000 Subject: [PATCH] Update SIPs state --- _sips/sips/42.type.md | 90 ++++++++++++------------- _sips/sips/alternative-bind-patterns.md | 7 ++ _sips/sips/multiple-assignments.md | 7 ++ _sips/sips/named-tuples.md | 4 +- 4 files changed, 61 insertions(+), 47 deletions(-) create mode 100644 _sips/sips/alternative-bind-patterns.md create mode 100644 _sips/sips/multiple-assignments.md diff --git a/_sips/sips/42.type.md b/_sips/sips/42.type.md index f143c9a8a..c35552cf5 100644 --- a/_sips/sips/42.type.md +++ b/_sips/sips/42.type.md @@ -33,17 +33,17 @@ their role is to give the meaning of paths selecting types and terms from nested paths have an intuitive meaning to programmers from a wide range of backgrounds which belies their underpinning by a somewhat "advanced" concept in type theory. -Nevertheless, by pairing a type with it's unique inhabitant, singleton types bridge the gap between -types and values, and their presence in Scala has over the years allowed Scala programmers to explore -techniques which would typically only be available in languages, such as Agda or Idris, with support +Nevertheless, by pairing a type with its unique inhabitant, singleton types bridge the gap between +types and values, and their presence in Scala has, over the years, allowed Scala programmers to explore +techniques which would typically only be available in languages such as Agda or Idris, with support for full-spectrum dependent types. Scala's semantics have up until now been richer than its syntax. The only singleton types which are currently _directly_ expressible are those of the form `p.type` where `p` is a path pointing to a value of some subtype of `AnyRef`. Internally the Scala compiler also represents singleton types for -individual values of subtypes of `AnyVal`, such as `Int` or values of type `String` which don't +individual values of subtypes of `AnyVal`, such as `Int` or values of type `String`, which don't correspond to paths. These types are inferred in some circumstances, notably as the types of `final` -vals. Their primary purpose has been to represent compile time constants (see [6.24 Constant +vals. Their primary purpose has been to represent compile-time constants (see [6.24 Constant Expressions](https://scala-lang.org/files/archive/spec/2.12/06-expressions.html#constant-expressions) and the discussion of "constant value definitions" in [4.1 Value Declarations and Definitions](https://scala-lang.org/files/archive/spec/2.12/04-basic-declarations-and-definitions.html#value-declarations-and-definitions)). @@ -89,15 +89,15 @@ Lightbend Scala compiler. foo(1: 1) // type ascription ``` -+ The `.type` singleton type forming operator can be applied to values of all subtypes of `Any`. - To prevent the compiler from widening our return type we assign to a final val. ++ The `.type` singleton-type-forming operator can be applied to values of all subtypes of `Any`. + To prevent the compiler from widening our return type, we assign to a final val. ``` def foo[T](t: T): t.type = t final val bar = foo(23) // result is bar: 23 ``` + The presence of an upper bound of `Singleton` on a formal type parameter indicates that - singleton types should be inferred for type parameters at call sites. To help see this + singleton types should be inferred for type parameters at call sites. To help see this, we introduce type constructor `Id` to prevent the compiler from widening our return type. ``` type Id[A] = A @@ -118,7 +118,7 @@ Lightbend Scala compiler. ``` + A `scala.ValueOf[T]` type class and corresponding `scala.Predef.valueOf[T]` operator has been - added yielding the unique value of types with a single inhabitant. + added, yielding the unique value of types with a single inhabitant. ``` def foo[T](implicit v: ValueOf[T]): T = v.value foo[13] // result is 13: Int @@ -129,13 +129,13 @@ Lightbend Scala compiler. Many of the examples below use primitives provided by the Scala generic programming library [shapeless](https://github.com/milessabin/shapeless/). It provides a `Witness` type class and a -family of Scala macro based methods and conversions for working with singleton types and shifting +family of Scala-macro-based methods and conversions for working with singleton types and shifting from the value to the type level and vice versa. One of the goals of this SIP is to enable Scala programmers to achieve similar results without having to rely on a third party library or fragile and non-portable macros. The relevant parts of shapeless are excerpted in [Appendix 1](#appendix-1--shapeless-excerpts). -Given the definitions there, some of forms summarized above can be expressed in current Scala, +Given the definitions there, some of the forms summarized above can be expressed in current Scala, ``` val wOne = Witness(1) val one: wOne.T = wOne.value // wOne.T is the type 1 @@ -147,13 +147,13 @@ foo[wOne.T] // result is 1: 1 "foo" ->> 23 // shapeless record field constructor // result type is FieldType["foo", Int] ``` -The syntax is awkward and hiding it from library users is challenging. Nevertheless they enable many +The syntax is awkward, and hiding it from library users is challenging. Nevertheless they enable many constructs which have proven valuable in practice. #### shapeless records shapeless models records as HLists (essentially nested pairs) of record values with their types -tagged with the singleton types of their keys. The library provides user friendly mechanisms for +tagged with the singleton types of their keys. The library provides user-friendly mechanisms for constructing record _values_, however it is extremely laborious to express the corresponding _types_. Consider the following record value, ``` @@ -165,7 +165,7 @@ val book = HNil ``` -Using shapeless and current Scala the following would be required to give `book` an explicit type +Using shapeless and current Scala, the following would be required to give `book` an explicit type annotation, ``` val wAuthor = Witness("author") @@ -241,20 +241,20 @@ val c: Int Refined Greater[w6.T] = a ^ ``` -Under this proposal we can express these refinements much more succinctly, +Under this proposal, we can express these refinements much more succinctly, ``` val a: Int Refined Greater[5] = 10 val b: Int Refined Greater[4] = a ``` -Type level predicates of this kind have proved to be useful in practice and are supported by modules +Type-level predicates of this kind have proved to be useful in practice and are supported by modules of a [number of important libraries](https://github.com/fthomas/refined#external-modules). Experience with those libraries has led to a desire to compute directly over singleton types, in -effect to lift whole term-level expressions to the type-level which has resulted in the development +effect to lift whole term-level expressions to the type level, which has resulted in the development of the [singleton-ops](https://github.com/fthomas/singleton-ops) library. singleton-ops is built -with Typelevel Scala which allows it to use literal types as discussed in this SIP. +with Typelevel Scala, which allows it to use literal types, as discussed in this SIP. ``` import singleton.ops._ @@ -279,7 +279,7 @@ singleton-ops is used by a number of libraries, most notably our next motivating [Libra](https://github.com/to-ithaca/libra) is a a dimensional analysis library based on shapeless, spire and singleton-ops. It support SI units at the type level for all numeric types. Like -singleton-ops Libra is built using Typelevel Scala and so is able to use literal types as discussed +singleton-ops, Libra is built using Typelevel Scala and so is able to use literal types, as discussed in this SIP. Libra allows numeric computations to be checked for dimensional correctness as follows, @@ -324,7 +324,7 @@ case class Residue[M <: Int](n: Int) extends AnyVal { } ``` -Given this definition we can work with modular numbers without any danger of mixing numbers with +Given this definition, we can work with modular numbers without any danger of mixing numbers with different moduli, ``` @@ -342,7 +342,7 @@ fiveModTen + fourModEleven ``` Also note that the use of `ValueOf` as an implicit argument of `+` means that the modulus does not -need to be stored along with the `Int` in the `Residue` value which could be beneficial in +need to be stored along with the `Int` in the `Residue` value, which could be beneficial in applications which work with large datasets. ### Proposal details @@ -360,7 +360,7 @@ applications which work with large datasets. | ‘(’ Types ‘)’ ``` - Examples, + Examples: ``` val one: 1 = 1 // val declaration def foo(x: 1): Option[1] = Some(x) // param type, type arg @@ -368,7 +368,7 @@ applications which work with large datasets. foo(1: 1) // type ascription ``` -+ The restriction that the singleton type forming operator `.type` can only be appended to ++ The restriction that the singleton-type-forming operator `.type` can only be appended to stable paths designating a value which conforms to `AnyRef` is dropped -- the path may now conform to `Any`. Section [3.2.1](https://scala-lang.org/files/archive/spec/2.12/03-types.html#singleton-types) of the SLS is @@ -385,7 +385,7 @@ applications which work with large datasets. > denoted by `p` (i.e., the value `v` for which `v eq p`). Where the path does not conform to > `scala.AnyRef` the type denotes the set consisting of only the value denoted by `p`. - Example, + Example: ``` def foo[T](t: T): t.type = t final val bar = foo(23) // result is bar: 23 @@ -471,7 +471,7 @@ applications which work with large datasets. > corresponding to a singleton-apt definition, or (2) The upper bound Ui of Ti conforms to > `Singleton`. - Example, + Example: ``` type Id[A] = A def wide[T](t: T): Id[T] = t @@ -483,17 +483,17 @@ applications which work with large datasets. Note that we introduce the type constructor `Id` simply to avoid widening of the return type. + A `scala.ValueOf[T]` type class and corresponding `scala.Predef.valueOf[T]` operator has been - added yielding the unique value of types with a single inhabitant. + added, yielding the unique value of types with a single inhabitant. Type inference allows us to infer a singleton type from a literal value. It is natural to want to be able to go in the other direction and infer a value from a singleton type. This latter capability was exploited in the motivating `Residue` example given earlier, and is widely relied - on in current Scala in uses of shapeless's records, and `LabelledGeneric` based type class + on in current Scala in uses of shapeless's records, and `LabelledGeneric`-based type class derivation. - Implicit resolution is Scala's mechanism for inferring values from types and in current Scala + Implicit resolution is Scala's mechanism for inferring values from types, and in current Scala, shapeless provides a macro-based materializer for instances of its `Witness` type class. This SIP - adds a directly compiler supported type class as a replacement, + adds a directly compiler-supported type class as a replacement: ``` final class ValueOf[T](val value: T) extends AnyVal @@ -502,20 +502,20 @@ applications which work with large datasets. Instances are automatically provided for all types with a single inhabitant, which includes literal and non-literal singleton types and `Unit`. - Example, + Example: ``` def foo[T](implicit v: ValueOf[T]): T = v.value foo[13] // result is 13: Int ``` - A method `valueOf` is also added to `scala.Predef` analogously to existing operators such as + A method `valueOf` is also added to `scala.Predef`, analogously to existing operators such as `classOf`, `typeOf` etc. ``` def valueOf[T](implicit vt: ValueOf[T]): T = vt.value ``` - Example, + Example: ``` object Foo valueOf[Foo.type] // result is Foo: Foo.type @@ -531,11 +531,11 @@ applications which work with large datasets. where the `TypePat` is a literal type is translated as a match against the subsuming non-singleton type followed by an equality test with the value corresponding to the literal type. - Where applied to literal types `isInstanceOf` is translated to a test against + Where applied to literal types, `isInstanceOf` is translated to a test against the subsuming non-singleton type and an equality test with the value corresponding to the literal type. - Examples, + Examples: ``` (1: Any) match { case one: 1 => true @@ -544,28 +544,28 @@ applications which work with large datasets. (1: Any).isInstanceOf[1] // result is true: Boolean ``` - Importantly, that doesn't include `asInstanceOf` as that is a user assertion to the compiler, with + Importantly, that doesn't include `asInstanceOf`, as that is a user assertion to the compiler, with the compiler inserting in the generated code just enough code for the underlying runtime to not give a `ValidationError`. The compiler should not, for instance, generate code such that an expression like `(1: Any).asInstanceOf[2]` would throw a `ClassCastException`. + Default initialization for vars with literal types is forbidden. - The default initializer for a var is already mandated to be it's natural zero element (`0`, - `false`, `null` etc.). This is inconsistent with the var being given a non-zero literal type, + The default initializer for a var is already mandated to be its natural zero element (`0`, + `false`, `null` etc.). This is inconsistent with the var being given a non-zero literal type: ``` var bad: 1 = _ ``` - Whilst we could, in principle, provide an implicit non-default initializer for cases such as these + Whilst we could, in principle, provide an implicit non-default initializer for cases such as these, it is the view of the authors of this SIP that there is nothing to be gained from enabling this - construction and that default initializer should be forbidden. + construction, and that default initializer should be forbidden. -## Follow on work from this SIP +## Follow-on work from this SIP Whilst the authors of this SIP believe that it stands on its own merits, we think that there are two -areas where follow on work is desirable, and one area where another SIP might improve the implementation of SIP-23. +areas where follow-on work is desirable, and one area where another SIP might improve the implementation of SIP-23. ### Infix and prefix types @@ -573,7 +573,7 @@ areas where follow on work is desirable, and one area where another SIP might im has emerged from the work on refined types and computation over singleton types mentioned in the motivation section above. -Once literal types are available it is natural to want to lift entire expressions to the type level +Once literal types are available, it is natural to want to lift entire expressions to the type level as is done already in libraries such as [singleton-ops](https://github.com/fthomas/singleton-ops). However, the precedence and associativity of symbolic infix _type constructors_ don't match the precedence and associativity of symbolic infix _value operators_, and prefix type constructors don't @@ -583,12 +583,12 @@ terms. ### Byte and short literals `Byte` and `Short` have singleton types, but lack any corresponding syntax either at the type or at the term level. -These types are important in libraries which deal with low level numerics and protocol implementation +These types are important in libraries which deal with low-level numerics and protocol implementation (see eg. [Spire](https://github.com/non/spire) and [Scodec](https://github.com/scodec/scodec)) and elsewhere, and the ability to, for instance, index a type class by a byte or short literal would be valuable. -A prototype of this syntax extension existed at an early stage in the development of Typelevel Scala +A prototype of this syntax extension existed at an early stage in the development of Typelevel Scala, but never matured. The possibility of useful literal types adds impetus. ### Opaque types @@ -610,7 +610,7 @@ would be elided, and the `valueOf[A]` method would be compiled to an identity fu ## Appendix 1 -- shapeless excerpts -Extracts from shapeless relevant to the motivating examples for this SIP, +Extracts from shapeless relevant to the motivating examples for this SIP: ``` trait Witness { diff --git a/_sips/sips/alternative-bind-patterns.md b/_sips/sips/alternative-bind-patterns.md new file mode 100644 index 000000000..871508d44 --- /dev/null +++ b/_sips/sips/alternative-bind-patterns.md @@ -0,0 +1,7 @@ +--- +title: SIP-60 - Alternative bind patterns +status: under-review +pull-request-number: 74 +stage: design + +--- diff --git a/_sips/sips/multiple-assignments.md b/_sips/sips/multiple-assignments.md new file mode 100644 index 000000000..19335b3fe --- /dev/null +++ b/_sips/sips/multiple-assignments.md @@ -0,0 +1,7 @@ +--- +title: SIP-59 - Multiple assignments +status: under-review +pull-request-number: 73 +stage: design + +--- diff --git a/_sips/sips/named-tuples.md b/_sips/sips/named-tuples.md index 6e1589633..82bc14181 100644 --- a/_sips/sips/named-tuples.md +++ b/_sips/sips/named-tuples.md @@ -1,7 +1,7 @@ --- title: SIP-58 - Named Tuples -status: submitted +status: under-review pull-request-number: 72 -stage: pre-sip +stage: design ---