One of important use cases for Named tuples could be addressing in a simpler way the current problem of expressing data structures with mapped field types. For example, scalasql
library uses the higher kinded data
pattern:
case class City[T[_]](
id: T[Int],
name: T[String],
countryCode: T[String],
district: T[String],
population: T[Long]
)
object City extends Table[City]
This pattern allows a case class to serve as a model (with identity HKT) and the dsl query structure (where fields are wrapped with a sql-specific HKT).
One could argue that the possibility of mapping data structure fields should not be required to be written out explicitly, especially with the complex concept of HKT. It could be assumed as a property of this class by some language features. Named tuples seem to be a really good fit for this feature, as we already have match types operating on tuples in Scala, and they could work as well on the named tuples:
case class City(
id: Int,
name: String,
countrycode: String,
district: String,
population: Long
)
type AsSql[Xs <: NamedTuple] = Xs match
case x *: xs => Sql[x] *: AsSql[xs]
case EmptyNamedTuple => EmptyNamedTuple
/* Assuming that case class <: specific NamedTuple, when the field contract is true */
def sql[A <: NamedTuple]: AsSql[A] =
/* Some dynamic magic*/
/* If the property of case class <: specific NamedTuple is not true, we could as well:*/
transparent inline def sql[A <: Product]: AsSql[ToNamedTuple[A]] =
/* Some dynamic magic */
sql[City] // => sql: (id: Sql[Int], name: Sql[String], countrycode: Sql[String], ...)
This way, the model can be kept simple, and the type system would allow for this kind of flexibility without exposing the user to the internal works of it. There would be the match type - but hidden, instead of exposed HKT. For the user, it would be just a type.
The main difference between named tuples and structural types in that case is that the named tuples are aware of being algebraic products (with all its benefits and flexibility)