2015-01-06 90 views
2

msdn页面记录Records (F#)详细信息record expressions为记录构造和record patterns为解构,后者没有命名为它们。 下面是其中同时使用技术算术运算符的例子:构建和解构记录

// 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 } 

这看似笨拙,不是很可读。对于解构,有点符号或功能作为替代。由于点符号操作符在规范(an expression’s type may be inferred from a record label)的8.4.2节名称分辨率和记录字段标签中有特殊配置,通常不需要注释。 Accessor功能像let u { U = u } = u不会给我们任何优势。

对于构造,我认为可以为一个函数作为记录构造函数。原来的构造函数访问甚至可以被限制:

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) 

这是一个地道的事是什么?如何在模块中打包这些函数并处理命名空间问题?

回答

4

简而言之:我认为目前这里没有一个通用的约定,所以最终会是个人决定。

总之你免费在F#记录的是:

  • 构建:{ U = u; V = v }(括号表示法)

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

  • 更新:{record with U = u}(方括号)

但是,如果您希望您可以手动编写它们,您不会获得免费的头等功能。

下面是什么,我会亲自使用的约定:

一个static member New与备案建设令行禁止参数。

对于更新和解构,我会使用某种Lenses抽象。

下面的代码的一个例子,我将不得不手工添加:

// 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 

这样,我就对建筑,解构也更新以及其他非常有趣的镜头性能,你可以第一类函数read in this post

UPDATE(响应您的意见)

当然,他们可以在以后定义,是什么改变? 这同样适用于New构造函数,它可以在后面定义,但这实际上是一件好事。 您定义的访问器函数也可以稍后定义,事实上任何第一类getter,setter或updater值都可以稍后定义。

无论如何,你的问题的答案是“不,没有约定”,其余的是个人决定,这将是我的决定,许多哈斯克勒也在努力为Haskell记录获取某种自动镜头。

为什么我会决定这样去?因为就代码行而言,添加简单访问器函数的工作与添加get-Lens几乎相同,因此以相同的价格获得更多功能。

如果您对镜头讨论不满意,请告诉我,我可以删除它并留下简短的答案,或者我可以删除整个答案,如果它是混淆而不是澄清。

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

构图不是透镜的唯一优点,你可以做许多事情,不断阅读它们,它们提供了一个非常有趣的抽象,而不仅仅限于记录。

+0

尽管镜头非常适合组合,但我并没有完全跟踪您在定义某些数据结构时内在实现它们的好处。正如你的[链接](http://bugsquash.blogspot.fr/2011/11/lenses-in-f.html)通过扩展方法演示的那样,它们也可以追溯地引入。这个问题的动机是希望避免在简洁和可读性方面重构记录定义。无论如何,如果您能稍后将镜头锁定,镜头如何帮助我? – kaefer

+0

@kaefer我在更新中回答了你。 – Gustavo