2011-11-23 57 views
2

假設我定義的模塊來處理與計量單位向量在F#:簡化F#記錄分配

module Vec 

    [<Measure>] 
    type m 

    type Vector3<[<Measure>] 'a> = 
     { 
     X : float<'a> 
     Y : float<'a> 
     Z : float<'a> 
     } 

現在我想創建一個變量let拿着Vector3。我可以這樣做:

let my_var : Vector3<m> = {X = 1.0<m> ; Y = 1.0<m> ; Z = 1.0<m>}; 

我必須做很多類似上面的任務,所以我想知道,有沒有什麼辦法,簡化了以前的語法?喜歡的東西:

let my_var : Vector3<m> = { 1.0,1.0,1.0} //this don't compile 
let my_var : Vector3<m> = {1.0<m> ; 1.0<m> ; 1.0<m>} //this don't compile either 

我想:

  1. 避免測量單元規格(1.0<m>),這可能嗎?是不是m暗示可以從聲明my_var : Vector3<m>導出?
  2. 避免使用記錄字段名稱(如第二個示例中所示)。基於命令,編譯器本身是否可以導出記錄的字段名稱?

回答

4

避免測量單位規範(1.0),這可能嗎?是不是可以從聲明my_var中導出:Vector3?

實際上,1.0相當於1.0 < 1>,因此您不能在預期不是1的度量(無量綱)的上下文中使用它。

但是,您可以使用1.0 < _>進行推理。

避免使用記錄字段名稱(如第二個示例中所示)。基於命令,編譯器本身是否可以導出記錄的字段名稱?

我能想到的最接近的是以下幾點:

type Vector3<[<Measure>] 'a> = 
    val X : float<'a> 
    val Y : float<'a> 
    val Z : float<'a> 
    new(x, y, z) = { X = x; Y = y; Z = z } 

然後可以使用這樣的:

let my_var = Vector3<m>(1.0<_>, 1.0<_>, 1.0<_>) 
+0

哦thanks..the新的建議是非常有用的.. – Heisenbug

5

我不認爲你需要指定類型對於你自己的變量,讓F#做類型推斷。所以,下面的聲明是不夠的:

let my_var = {X = 1.0<m> ; Y = 1.0<m> ; Z = 1.0<m>} 

如果您不希望指定記錄的字段名(我認爲這是很好的使你的程序清楚),您可以將記錄更改爲類(像@塔米爾的答案)或不相交的聯盟。就個人而言,我喜歡不交併更多,因爲我仍然可以在模式中使用它們很容易匹配:

type Vector3<[<Measure>] 'a> = Vector3 of float<'a> * float<'a> * float<'a> 

let my_var1 = Vector3(1.0, 1.0, 1.0) // Vector3<1> 
let my_var2 = Vector3(1.0<m>, 1.0<_>, 1.0<_>) // Vector3<m> 
+0

脫節工會的不便,不過,是你可以使用點符號來訪問單個字段。您可以通過使用類併爲其編寫一個活動模式來充分利用這兩個世界,但是這會開始形成很多代碼,所以如果您有這種情況,您可能不想這樣做許多這樣的類型來寫。 – Tarmil