2015-01-06 100 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