Problem: Parameter Explosion
The removal of type projection (T#A) in Scala 3 prevents us from accessing the arguments of a higher-kinded type parameter. This forces us to “lift” every internal type variable into the class signature.
This is not just combinatorially verbose; it breaks encapsulation. We are forced to declare “useless” parameters—implementation details of the child components—solely to reconstruct the return type in the extends clause.
Example
Consider a Pipe defined by an Input Schema and an Output Schema.
Schemahas 2 parameters:Rowtype andValidatortype.- Merging two Pipes requires merging their schemas (Union of Rows, Intersection of Validators).
trait Schema[+Row, -Val]
trait Pipe[I <: Schema[?,?], O <: Schema[?,?]]
Current Scala (12 Parameters)
To implement MergePipes, we cannot simply take two Pipes. We must extract R1, V1 etc., because the MergeLogic in the extends clause requires them explicitly.
// The Type Logic (Operator)
// We are forced to define this on the raw components
trait MergeLogic[R1, V1, R2, V2] extends Schema[R1 | R2, V1 & V2]
case class MergePipes[
// Left Pipe Internals
IR1, IV1, I1 <: Schema[IR1, IV1],
OR1, OV1, O1 <: Schema[OR1, OV1],
// Right Pipe Internals
IR2, IV2, I2 <: Schema[IR2, IV2],
OR2, OV2, O2 <: Schema[OR2, OV2]
](
left: Pipe[I1, O1],
right: Pipe[I2, O2]
) extends Pipe[
// Visual Noise: We must manually thread the useless params here
MergeLogic[IR1, IV1, IR2, IV2],
MergeLogic[OR1, OV1, OR2, OV2]
]
Proposed Syntax (2 Parameters)
We define MergeLogic to accept the Schema containers directly, using projection to access Row and Val internally. The MergePipes class now only takes the two pipes.
// The Type Logic (Refactored)
// Now accepts the containers and projects internally
trait MergeLogic[S1 <: Schema[?,?], S2 <: Schema[?,?]]
extends Schema[S1#Row | S2#Row, S1#Val & S2#Val]
type PTop = Pipe[?, ?]
case class MergePipes[P1 <: PTop, P2 <: PTop](left: P1, right: P2)
extends Pipe[
// Clean: We extract the schemas from the pipes via projection
MergeLogic[P1#I, P2#I],
MergeLogic[P1#O, P2#O]
]
The Proposal
Allow C#T only if C has an upper bound that defines the type parameter T.
This is not general type projection. It is only (equivalent to) syntactic sugar for the explicit parameter version.