scala - 如何管理函数式编程中的状态层次结构?
问题描述
假设我有一个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
类)存在。所以如果我想调用一个学生的动作,我必须调用proxy function
Environment 类的暴露。如果我在 中有很多动作Student
,我必须在 中编写相同数量的代理函数School
,这很令人沮丧,而且一点也不好玩。
有什么建议吗?如何管理这种状态层次结构?
解决方案
受@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,而不是一堆不同深度的代理函数,酷!
推荐阅读
- c# - 在 C# 中使用 WebClient 读取 404 页面的源代码?
- python-3.x - 在 Python3 中将 XML 文件发送到 REST API
- scala - scala - 单元测试 - 如何在类中模拟类方法
- vba - 从 WORD 表 VBA 中获取公式值
- javascript - IE11中的JSON对象描述是否可能
- ios - 我可以将客户端在线支付门户与 iOS 应用程序一起使用吗?
- git - git-ftp:不是 git 命令
- javascript - 未捕获的 ReferenceError: L 未定义
- javascript - 检查数组javascript中的数字
- pandas - 解析4个数据框和一个fasta文件