说我有一个Student
类,其中包含很多动作:
final case class Student(name: String, knowledge: List[String]) {
def learn(item: String) : Student = this.copy(knowledge = knowledge :+ item)
}
在这里您会注意到,此类不受任何外部国家的影响。
但是,如果我将此类放在有状态的环境中(例如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
}
}
}
然后我不能直接使用student.learn(info)
,因为Student
甚至不知道环境(School
类)是否存在。因此,如果我想调用学生的动作,则必须调用Environment类公开的proxy function
。如果我在Student
中有很多动作,我必须在School
中编写相同数量的代理函数,这很令人沮丧而且一点也不有趣。
有什么建议吗?如何管理这种状态层次结构?
答案 0 :(得分:2)
受@WillemVanOnsem的启发,这是我的解决方案。
def updateStudent: String => (Student => Student) => School =
name =>
func =>
this.copy(
students = students + (name -> func(
students.get(name).getOrElse(Student(name, List()))
))
)
用法如下:
val stu1 = Student("name1", List())
val school = School(Map(stu1.name -> stu1))
val newSchool = school.updateStudent("name1") { student =>
student.learn("someItem")
}
我注意到,如果您的层次结构确实很深,(Student => Student)
部分可以由Lens代替,那么您应该准备一堆Lens,而不是一堆功能深度不同的代理函数,酷!