ak.*_*ak. 7 dns modeling functional-programming scala object
我目前正试图围绕Scala进行思考,并打算将它用于我的下一个必须处理DICOM的项目.DICOM具有相当广泛的规范,涵盖了数千页的标准.我对DICOM的理解非常有限,但简而言之,DICOM对象 - IOD(信息对象定义)由模块组成,而模块是类型名称 - 值属性对的集合.一些模块和属性的可选性进一步复杂化.例如:
SimpleImageIOD: {
PatientModule: {
name: String
dateOfBirth: DateTime
}
StudyModule: {
name: String
date: DateTime (optional)
}
SeriesModule: {
name: String
}
ImageModule: {
height: Integer
width: Integer
pixelSize: Double (optional)
}
EquipmentModule: { (optional)
type: String
}
}
Run Code Online (Sandbox Code Playgroud)
有大量的模块,它们可能以各种组合形成不同的IOD.Scala反过来拥有大量的建模能力,包括所有特征,案例类,动态类等.你会如何在Scala中建模这样的域?我对语言很新,但我一直在考虑使用不可变的case类来定义模块,然后将它们聚合在各种IOD中,并使用镜头进行更新:
case class Patient(name: String, dateOfBirth: DateTime)
case class Study(name: String, date: Option[DateTime])
case class Series(name: String)
case class Image(height: Integer, width: Integer, pixelSize: Option[Double])
case class Equipment(type: String)
case class SimpleImageIOD(patient: Patient, study: Study, series: Series,
image: Image, equipment: Option[Equipment])
object Patient {
val nameL: Lens[Patient, String] = ...
val dateOfBirthL: Lens[Patient, DateTime] = ...
}
object SimpleImageIOD {
val patientL: Lens[SimpleImageIOD, Patient] = ...
val patientNamel = patientL andThen Patient.nameL
}
Run Code Online (Sandbox Code Playgroud)
等等.对于镜头来说,编码所有样板可能会成为一个问题 - M x N x L镜头的顺序将覆盖整个域的MIOD,N模块和L属性.此外,某些领域的选择性至少使得任务变得非常复杂scalaz-seven.
还有哪些可行的方法可以与Scala的精神保持一致?
你可以嵌入镜片,所以我认为你不会有M x N x L镜片.我认为这是一种非常合理的方法.
另一种方法是定义您自己的单项更新方法,如下所示:
case class Patient(name: String, dateOfBirth: Long) {
def name(f: String => String): Patient = copy(name = f(name))
def dateOfBirth(f: Long => Long): Patient = copy(dateOfBirth = f(dateOfBirth))
}
Run Code Online (Sandbox Code Playgroud)
你喜欢这样使用:
scala> Patient("John",0).name(_ + " Smith")
res1: Patient = Patient(John Smith,0)
Run Code Online (Sandbox Code Playgroud)
这是透镜可以实现的,但你必须非常小心,避免使用更多的样板(在使用和定义上).它没有镜头的灵活性,你可以任意拉开功能(例如更新),但它通过简化来弥补它.
我通过这种方式进行了大部分深度更新:
myImage.patient(_.study(_.date(_ => Some(System.currentTimeMillis))))
Run Code Online (Sandbox Code Playgroud)
你只需要用当前时间的研究来更新整个树(假装这里DateTime实际上是a Long),如果你真的需要提取这种特殊树的再生能力(这对于镜片来说更自然),你可以
val setStudyTime = (t: Long) => myImage.patient(_.study(_.date(_ => Some(t))))
Run Code Online (Sandbox Code Playgroud)
甚至
def studyTimeSetter(si: SimpleImageIOD) =
(t: Long) => si.patient(_.study(_.date(_ => Some(t))))
Run Code Online (Sandbox Code Playgroud)
如果您需要立即轻松获取此功能.
如果你需要镜头为你提供的所有东西,那么使用这种方法以特别的方式重建它是更多的工作,但如果你只需要一小部分而且大部分只是需要减少样板来进行设置,这样做相当不错工作.
| 归档时间: |
|
| 查看次数: |
1635 次 |
| 最近记录: |