构造和解构记录 [英] Constructing and deconstructing records

查看:52
本文介绍了构造和解构记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

记录了记录(F#)的msdn页详细信息记录表达式用于记录构造,而记录模式用于解构,后者没有这样命名.这是一个将两种技术都用于算术运算符的示例:

The msdn page documenting Records (F#) details record expressions for record construction and record patterns for deconstruction, the latter without naming them as such. Here's an example which uses both techniques for an arithmetic operator:

// Simple two-dimensional generic vector defintion
type 'a UV =
    { U : 'a; V : 'a }
    static member inline (+) ({ U = au; V = av }, { U = bu; V = bv }) =
        { U = au + bu; V = av + bv }

这看起来很笨拙,而且不太可读.对于解构,可以使用点符号或替代功能.由于在规范的8.4.2部分名称解析和记录字段标签中,点符号运算符具有特殊的含义(可以从记录标签中推断出表达式的类型),通常无需注释.像 let u {U = u} = u 这样的访问器函数将不会给我们带来任何好处.

This appears unwieldy and not very readable. For deconstruction, there are dot-notation or functions as alternatives. Since the dot-notation operator has a special dispensation in section 8.4.2 Name Resolution and Record Field Labels of the spec (an expression’s type may be inferred from a record label), there's normally no need to annotate. Accessor functions like let u { U = u } = u wouldn't give us any advantages then.

对于构造,我认为可以作为记录构造函数使用.甚至可能会限制对原始构造函数的访问:

For construction, I think a case can be made for a function as record constructor. Access to the original constructor might even be restricted:

type 'a UV =
    internal { U : 'a; V : 'a }
let uv u v = { U = u; V = v }
type 'a UV with
    static member inline (+) (a, b) =
        uv (a.U + b.U) (a.V + b.V)

这是惯常的做法吗?如何将这些函数打包到模块中并处理名称空间问题?

Is this an idiomatic thing to do? How to package such functions in modules and handle namespace issues?

推荐答案

简短的回答:我认为目前尚无常规,因此最终将由个人决定.

Short answer: I don't think there is a general convention here at the moment so it will be a personal decision in the end.

总结使用F#中的记录免费获得的 是:

To summarise what you get for free with records in F# is:

  • 构造: {U = u;V = v} (括号符号)

解构: let u = record.u (点符号)和 let {U = u} = record (模式匹配)

Deconstruct: let u = record.u (dot-notation) and let {U = u} = record (pattern matching)

更新: {记录为U = u} (带括号的符号)

Update: {record with U = u} (bracket-notation)

但是,如果您愿意,可以免费编写一流的函数.

But you don't get first class functions for free, if you want you can code them by hand.

以下是我个人用作约定的内容:

The following is what I would personally use as convention:

一个带有静态参数的静态成员New 用于记录的构建.

A static member New with curried arguments for record construction.

对于更新和解构,我将使用某种

For update and deconstruction I would use some kind of Lenses abstraction.

这是我必须手动添加的代码示例:

Here's an example of the code I would have to add by hand:

// Somewhere as a top level definition or in a base library
type Lens<'T,'U> = {Get: 'T -> 'U; Set: 'U -> 'T -> 'T } with
  member l.Update f a = l.Set (f (l.Get a)) a


type UV<'a> = {U : 'a; V : 'a } with
// add these static members to your records
  static member New u v : UV<'a> = {U = u; V = v}
  static member u = {Get = (fun (x: UV<'a>) -> x.U); Set = fun t x -> {x with U = t}}
  static member v = {Get = (fun (x: UV<'a>) -> x.V); Set = fun t x -> {x with V = t}}


let uvRecord  = UV.New 10 20
let u         = UV.u.Get uvRecord
let uvRecord1 = UV.u.Set (u+1) uvRecord
let uvRecord2 = UV.u.Update ((+)1) uvRecord

这样,我将拥有一流的构造,解构,更新功能以及其他非常有趣的Lenses属性,只要您

This way I would have first class functions for construction, deconstruction but also for updates plus other very interesting Lenses properties as you can read in this post.

更新(针对您的评论)

当然可以在以后定义它们,它会发生什么变化? New 构造函数也是如此,可以稍后定义,但这实际上是一件好事.您定义的访问器函数也可以在以后定义,实际上任何一流的getter,setter或updater值都可以在以后定义.

Of course they can be defined later, what does it change? The same applies for the New constructor, it can be defined later but that's actually a good thing. The accessor functions you defined can also be defined later, indeed any first-class getter, setter or updater value can be defined later.

无论如何,您的问题的答案是不,没有约定",其余的是个人决定,这将是我的决定,而且许多Haskellers都在努力为Haskell记录获取某种自动镜头.

Anyway the answer to your question is "no, there are no conventions" the rest it's a personal decision, which would be my decision and also many Haskellers are pushing to get some kind of automatic Lenses for Haskell records.

我为什么要选择这种方式?因为就代码行而言,添加简单访问器功能的工作几乎与添加get-Lens相同,所以以相同的价格可以获得更多功能.

Why would I decide to go this way? Because in terms of lines of code the effort of adding a simple accessor function is almost the same as adding a get-Lens, so for the same price I get more functionality.

如果您对Lenses的讨论不满意,请告诉我,我可以删除它并留下简短答案,或者如果它使您感到困惑而不是澄清,也可以删除整个答案.

If you are not happy with the Lenses discussion please tell me, I can delete it and leave the short answer, or I can delete the whole answer too if it's confusing instead of clarifying.

或者我可能误解了您的问题,对我来说,您的问题是关于通常使用哪种约定为记录添加一流的构造函数,getter和setter方法的值.

Or may be I misunderstood your question, for me your question was about which convention is generally used to add first-class constructors, getters and setters values for records.

合成不是Lenses的唯一优势,您可以做很多事情,继续阅读它们,它们提供了非常有趣的抽象,不仅限于记录.

Composition is not the only advantage of Lenses, you can do many things, keep reading about them, they provide a very interesting abstraction and not only restricted to records.

这篇关于构造和解构记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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