I'm using scala 3.3 to build a map
variable that temporarily stores a school's information like below.
Map's variable:
"staff" -> Set[CreateStaff]
"students" -> Set[CreateStudent]
"books" -> Set[CreateBook]
The map stores data inside heterogenous Set()
parameters.
The data is generated using case classes CreateStaff
, CreateStudent
and CreateBook
- traits of School
.
And I try to store the data inside the map variable above using the code mapOS("staff")+=newStaffA
which gives an error like below.
The same errors occur for the CreateStudent
and CreateBook
case classes , which I've omitted in the error text.
Error:
error: type mismatch;
found: Map[String,scala.collection.mutable.Set[_ >: this.CreateBook with this.CreateStudent with this.CreateStaff <: Product with this.School with java.io.Serializable]] (in scala.collection.mutable)
required: Map[String,Set[this.School]] (in scala.collection.immutable)
val mapOS: Map[String, Set[School]] = mutable.Map("staff" -> mutable.Set[CreateStaff](), "students" -> mutable.Set[CreateStudent](), "books" -> mutable.Set[CreateBook]())
error: value += is not a member of Set[this.School]
Expression does not convert to assignment because receiver is not assignable.
mapOS("staff")+=newStaffA
... OMITTED SIMILAR ERRORS FOR CreateStudent and CreateBook case classes
...
My current code looks like below.
Could you help me identify and fix the errors!
Thanks in advance for your help!
school.scala:
import scala.collection.immutable
import scala.collection.mutable
sealed trait School
final case class CreateStaff(id: String, name: String) extends School
final case class CreateStudent(id: String, name: String) extends School
final case class CreateBook(id: String, name: String) extends School
val mapOS: Map[String, Set[School]] = mutable.Map("staff" -> mutable.Set[CreateStaff](), "students" -> mutable.Set[CreateStudent](), "books" -> mutable.Set[CreateBook]())
val newStaffA: CreateStaff = CreateStaff("id1", "name1")
val newStaffB: CreateStaff = CreateStaff("id1", "name1")
val newStudentA: CreateStudent = CreateStudent("id1", "name1")
val newStudentB: CreateStudent = CreateStudent("id1", "name1")
val newBookA: CreateBook = CreateBook("id1", "name1")
val newBookB: CreateBook = CreateBook("id1", "name1")
mapOS("staff")+=newStaffA
mapOS("staff")+=newStaffB
mapOS("students")+=newStudentA
mapOS("students")+=newStudentB
mapOS("books")+=newBookA
mapOS("books")+=newBookB
println(mapOS.getOrElse("staff", Set.empty))
To build on a comment I had with regard to have a class instead of a map, here is an example of how this would look like if it was modeled as such:
final case class CreateStaff(id: String, name: String)
final case class CreateStudent(id: String, name: String)
final case class CreateBook(id: String, name: String)
final case class School(
staff: Set[CreateStaff] = Set.empty[CreateStaff],
students: Set[CreateStudent] = Set.empty[CreateStudent],
books: Set[CreateBook] = Set.empty[CreateBook],
)
val school = School()
val staff = CreateStaff("id1", "name1")
val student = CreateStudent("id1", "name1")
val book = CreateBook("id1", "name1")
val updatedSchool = school.copy(
staff = school.staff + staff,
students = school.students + student,
books = school.books + book,
)
println(updatedSchool.staff) // prints "Set(CreateStaff(id1,name1))"
This code is available for you to play around with here on Scastie.
A few comments on the decisions I took:
For completeness, this is the same example using mutable data structures instead:
import scala.collection.mutable
final case class CreateStaff(id: String, name: String)
final case class CreateStudent(id: String, name: String)
final case class CreateBook(id: String, name: String)
final class School(
val staff: mutable.Set[CreateStaff] = mutable.Set.empty[CreateStaff],
val students: mutable.Set[CreateStudent] = mutable.Set.empty[CreateStudent],
val books: mutable.Set[CreateBook] = mutable.Set.empty[CreateBook],
)
val school = new School()
val staff = CreateStaff("id1", "name1")
val student = CreateStudent("id1", "name1")
val book = CreateBook("id1", "name1")
school.staff += staff
school.students += student
school.books += book
println(school.staff) // prints "HashSet(CreateStaff(id1,name1))"
You can play around with this code here on Scastie.