F# - 我可以使用类型名称作为默认构造函数吗?

时间:2012-04-10 18:26:03

标签: 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)

有更好的方法吗?

4 个答案:

答案 0 :(得分: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指出的那样,可以使用更简单(并且更少hacky)的签名:

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

注意,这会切换类型args,因此它变为New<_, MyInt>

答案 1 :(得分: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 }

或者,您的解决方法是一个很好的解决方案。

答案 2 :(得分:1)

要对此进行更新 - F# 4.0已将构造函数升级为第一类函数,因此现在可以在任何可以使用函数或方法的地方使用它们。

答案 3 :(得分: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)