静态地“延伸”一个没有间接麻烦的记录数据类型 [英] Statically "extend" a record-ish data type without indirection hassle

查看:130
本文介绍了静态地“延伸”一个没有间接麻烦的记录数据类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用一个三级流程,我需要一些信息来访问和更新流程。这些信息也是三层的,这样一个层次的过程可能需要访问/更新其层次和更高层次的信息。

  type info_0 = {... fields ...} 
type info_1 = {... fields ...}
type info_2 = {... fields ... }

fun0 info_0 ,然后将它传递给 fun1 以及 info_1 ,然后找回结果 info_0 并继续,用另一个 info_1 调用另一个 fun1 code>。
同样发生在较低层次上。






我目前的表现形式为

  type info_0 = {... fields ...} 
type info_1 = {i0:info_0; ...字段...}
type info_2 = {i1:info_1; ...字段...}

fun2

  let fun2(i2)更新 info_0  :info_2):info_2 = 
{
i2 with
i1 = {
i2.i1 with
i0 = update_field0 i2.i1.i0
}

$ / code>






更简单的是: / p>

 输入info_0 = {...字段...} 
输入info_1 = {...字段... }
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)






最后的解决方案看起来不错吗?

有没有更好的解决方案来解决这类问题? (例如,我可以编写一个可以处理更新 field0 的函数,无论它是处理 info_0 info_1 info_2



模块有帮助? (我可以在 Sig1 内包含一个 Sig0 ,例如...)

的习惯方式。 我并不了解OCaml中的任何相关工作,但在Scala / Haskell中有一些技术可用,包括 Zippers 树重写功能性镜片


更清晰的方式来更新嵌套结构

是否有Haskell成语用于更新嵌套数据结构?



对于F#,OCaml的后代,功能镜头给出一个好的解决方案因此,镜片是最相关的方法。你可以从这个线程得到使用它的想法:



更新嵌套的不可变数据结构



因为F#记录语法几乎与OCaml相同。



编辑:

正如@Thomas在他的评论中提到的,OCaml中有一个完整的镜头实现< a href =https://github.com/astrada/gapi-ocaml =nofollow noreferrer>这里。特别是, gapiLens.mli 是我们的兴趣。

I am currently working with a three-level process for which I need some information to flow being accessed and updated. The information is also three-leveled, in such a way that a process at one level may need to access/update information at its level and at higher levels.

type info_0 = { ... fields ... }
type info_1 = { ... fields ... }
type info_2 = { ... fields ... }

fun0 will do some stuff with an info_0, then pass it to fun1 along with an info_1, then get back the resulting info_0 and proceed, calling another fun1 with another info_1. The same happens at the lower level.


My current representation has

type info_0 = { ... fields ... }
type info_1 = { i0: info_0; ... fields ... }
type info_2 = { i1: info_1; ... fields ... }

In fun2, updating info_0 get pretty messy:

let fun2 (i2: info_2): info_2 =
  {
    i2 with
      i1 = {
        i2.i1 with
          i0 = update_field0 i2.i1.i0
      }
  }


Something simpler would be:

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)


Does the last solution look good?

Is there an even better solution to this kind of problem? (for instance, one where I could write a function that can handle updating a field0, no matter whether it's dealing with a info_0, info_1 or info_2)

Would OCaml modules help? (I could include a Sig0 inside Sig1 for instance...)

解决方案

What you need is an idiomatic way of updating nested immutable data structures. I don't know any relevant work in OCaml, but there are a few techniques available in Scala/Haskell including Zippers, Tree rewriting, and Functional lenses:

Cleaner way to update nested structures

Is there a Haskell idiom for updating a nested data structure?

For F#, a descendant of OCaml, functional lenses gives a nice solution. Therefore, lenses is the most relevant approach here. You can get the idea of using it from this thread:

Updating nested immutable data structures

since F# record syntax is almost the same as that of OCaml.

EDIT:

As @Thomas mentioned in his comment, there is a complete implementation of lenses in OCaml available here. And particularly, gapiLens.mli is of our interest.

这篇关于静态地“延伸”一个没有间接麻烦的记录数据类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆