Practical problem:
Let's imagine the client of a spectacle-house makes a reservation for a concert.
Some tickets for the concert have a seat.
The client brings a spouse.
Restriction:
1. Either both the ticket of the client and the corresponding spouse's ticket are seated OR both are not seated.
How do I impose this restriction at the typelevel?
What I initially thought:
case class Ticket[S <: Option[String]](id: String, seat: S)
case class ConcertReservation[A <: Option[String]](userTicket: Ticket[A],
spouseTicket: Ticket[A])
val concertReservation =
ConcertReservation(
userTicket = Ticket(id = "id1", seat = Some("<seatId>")),
spouseTicket = Ticket(id = "id2", seat = None)
)
With this I wanted to impose, via the type parameter A on ConcertReservation[A]
, that userTicket and spouseTicket must be of the same type.
Doing this allows the compiler to catch the above violation of the restriction:
Error:(12, 26) type mismatch;
found : .....Temp.Ticket[Some[String]]
required: .....Ticket[Option[String]]
Note: Some[String] <: Option[String], but class Ticket is invariant in type S.
You may wish to define S as +S instead. (SLS 4.5)
userTicket = Ticket(id = "id1", seat = Some("assad")),
But it is possible to overcome this. For example with the code below (which compiles):
val concertReservation2: ConcertReservation[Option[String]] =
ConcertReservation(
userTicket = Ticket(id = "id1", seat = Some("assad")),
spouseTicket = Ticket(id = "id2", seat = None)
)
Is there a idiomatic way to achieve what I want? Some kind of "pattern" perhaps?
Thanks,