Pti*_*val 14 ocaml records functional-programming nested sml
我目前正在处理一个三级流程,我需要一些信息才能访问和更新.信息也是三级的,这样一个级别的过程可能需要在其级别和更高级别访问/更新信息.
type info_0 = { ... fields ... }
type info_1 = { ... fields ... }
type info_2 = { ... fields ... }
Run Code Online (Sandbox Code Playgroud)
fun0会用a做一些东西info_0,然后将它传递给fun1a info_1,然后返回结果info_0并继续,fun1用另一个调用另一个info_1.同样的情况发生在较低级别.
我目前的代表有
type info_0 = { ... fields ... }
type info_1 = { i0: info_0; ... fields ... }
type info_2 = { i1: info_1; ... fields ... }
Run Code Online (Sandbox Code Playgroud)
在fun2,更新info_0变得非常混乱:
let fun2 (i2: info_2): info_2 =
{
i2 with
i1 = {
i2.i1 with
i0 = update_field0 i2.i1.i0
}
}
Run Code Online (Sandbox Code Playgroud)
更简单的是:
type info_0 = { ... fields ... }
type info_1 = { ... fields ... }
type info_2 = { ... fields ... }
type info_01 = info_0 * info_1
type info_012 = info_0 * info_1 * info_2
let fun2 (i0, i1, i2): info_012 =
(update_field0 i0, i1, i2)
Run Code Online (Sandbox Code Playgroud)
最后的解决方案看起来不错吗?
是否有更好的解决方案来解决这类问题?(例如,我可以编写一个可以处理更新a的函数,field0无论它是否处理a info_0,info_1或者info_2)
OCaml模块会有帮助吗?(我可以包括一个Sig0内部Sig1......)
pad*_*pad 10
您需要的是更新嵌套的不可变数据结构的惯用方法.我不知道OCaml中的任何相关工作,但 Scala/Haskell中有一些技术可用,包括Zippers,Tree rewriting和Functional镜头:
对于OCaml的后代F#,功能镜头提供了一个很好的解决方案.因此,镜片是这里最相关的方法.您可以从这个线程中获得使用它的想法:
因为F#记录语法几乎与OCaml的语法相同.
编辑:
作为@Thomas在他的评论中提到的,在OCaml中可使用的镜头的完整实现在这里.特别是,gapiLens.mli符合我们的利益.
您似乎希望能够将更复杂的值视为更简单的值.这(或多或少)是OO模型的本质.我经常试图避免使用OCaml的OO子集,除非我真的需要它,但它似乎确实满足了你的需求.你会有一个对应的基类info_0.该类info_1将是它的子类info_0,并且info_2将是它的子类info_1.无论如何,这是值得思考的.
| 归档时间: |
|
| 查看次数: |
1064 次 |
| 最近记录: |