2012-04-10 59 views
6

要創建我的類的順序,F# - 我可以使用類型名稱作爲默認構造函數嗎?

type MyInt(i:int) = 
    member this.i = i 

[1;2;3] |> Seq.map(fun x->MyInt(x)) 

其中fun x->MyInt(x)似乎是多餘的。它會更好,如果我能寫Seq.map(MyInt)

但我不能。我能想到的一種解決方法是定義一個單獨的功能

let myint x = MyInt(x) 
[1;2;3] |> Seq.map(myint) 

有沒有更好的方法來做到這一點?

回答

7

總之,沒有。

對象構造不是F#一流的功能。這是一個理由不使用類,可識別聯合是更好地在這裏使用:

type myInt = MyInt of int 
let xs = [1;2;3] |> Seq.map MyInt 

如果你不喜歡明確的lambda表達式,序列表達式查找在你的榜樣更好:

let xs = seq { for x in [1;2;3] -> MyInt x } 

或者,您的解決方法是一個很好的解決方案。

9

如果無償黑客不打擾你,你可以這樣做:

///functionize constructor taking one arg 
let inline New< ^T, ^U when ^T : (static member ``.ctor`` : ^U -> ^T)> arg = 
    (^T : (static member ``.ctor`` : ^U -> ^T) arg) 

type MyInt(i: int) = 
    member x.i = i 

[0..9] |> List.map New<MyInt, _> 

編輯:由於KVB指出的,可以使用簡單(少哈克)簽名:

let inline New x = (^t : (new : ^u -> ^t) x) 

請注意,這會切換類型參數,因此它變成New<_, MyInt>

+0

你的'定義New'不會在VS11 Beta版編譯我。然而,一個更簡單的變體會:「讓內聯新的x =(^ t:(new:^ u - >^t)x)'。 – kvb 2012-04-10 20:33:07

+0

我首先嚐試了這個方法,但是當使用^ t:(new:^ u - >^t)時,顯式約束'^ t不能在VS2010中編譯。很高興知道有一個更簡單的方法來做到這一點。 – Daniel 2012-04-10 20:42:30

+0

奇怪的編譯器只支持形式'新的顯式構造的限制:單元 - >「t'(這是在.NET中的元數據直接表示的),但你能明顯使用更普遍的構造函數約束_invocation expressions_,讓編譯器推斷約束。這絕對是系統中的一個漏洞。 – kvb 2012-04-10 21:33:54

0

我爲此目的而使用靜態方法。其原因是,有時你的對象構造函數需要從不同的來源取兩個參數,而我的方法可以讓你用List.map2

type NumRange(value, range) = 
    static member Make aValue aRange = new NumRange(aValue, aRange) 

let result1 = List.map2 NumRange.Make values ranges 

部分應用程序不被禁止,以及:

let result2 = 
    values 
    |> List.map NumRange.Make 
    |> List.map2 id <| ranges 

如果你不喜歡在這裏使用id,您可以使用(fun x y -> x y)這更可讀。

1

爲此更新 - F# 4.0已將升級的構造函數升級爲一級函數,因此現在可以在任何可以使用函數或方法的地方使用它們。

相關問題