Ukonn Ra
Ukonn Ra

Reputation: 754

How to manage the hierarchy of State in Functional Programming?

Say I have a Student class which has lots of actions:

final case class Student(name: String, knowledge: List[String]) {
  def learn(item: String) : Student = this.copy(knowledge = knowledge :+ item)
}

Here you can notice that this class is not influenced by any outer State.

But if I put this class into a Stateful environment(like a School):

final case class School(students: Map[String, Student]) {
  def learn(studentName: String, item: String) : State[School, Student] = State {
    oldSchool => {
      val oldStudent = students.get(studentName).getOrElse(Student(studentName, List()))
      val newStudent = oldStudent.learn(item)
      oldSchool.copy(students = students + (studentName -> newStudent)) -> newStudent
    }
  }
}

And then I cannot use student.learn(info) directly, for Student even doesn't know the environment(School class) exists. So if I want to call the actions of a student, I have to call the proxy function exposed by the Environment class. If I have lots of actions in Student, I HAVE TO write the same count of proxy functions in School, which is frustrating and not fun at all.

Any advices? How to manage this kind of State hierarchy?

Upvotes: 3

Views: 295

Answers (1)

Ukonn Ra
Ukonn Ra

Reputation: 754

Inspired by @WillemVanOnsem, here is my solution.

  def updateStudent: String => (Student => Student) => School =
    name =>
      func =>
        this.copy(
          students = students + (name -> func(
            students.get(name).getOrElse(Student(name, List()))
          ))
        )

And the usage likes:

    val stu1   = Student("name1", List())
    val school = School(Map(stu1.name -> stu1))

    val newSchool = school.updateStudent("name1") { student =>
      student.learn("someItem")
    }

And I notice that if your hierarchy is really deep, the (Student => Student) part can be replaced by Lens, so the you should prepare a bunch of Lens, rather than a bunch of Proxy Functions of different depth of functions, cool!

Upvotes: 2

Related Questions