2012-04-10 10 views

Respuesta

7

En resumen, no.

Los constructores de objetos no son funciones de primera clase en F #. Esta es una razón más para no usar clases, discriminado sindicatos es mejor utilizar aquí:

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

Si no te gusta lambdas explícitas, la expresión de la secuencia se ve mejor en su ejemplo:

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

Alternativamente , su solución es una buena solución.

9

Si hacks gratuitos no te molestan, se podría hacer:

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

EDIT: Como kvb señaló, una firma más simple (y menos hacky) se puede utilizar:

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

Tenga en cuenta que esto cambia el tipo args alrededor, por lo que se convierte en New<_, MyInt>.

+0

Su definición de 'Nuevo' no compila para mí en el VS11 Beta. Sin embargo, una variante más simple hace: 'let inline New x = (^ t: (new:^u ->^t) x)'. – kvb

+0

Lo intenté primero, pero con restricciones explícitas '^ t cuando^t: (nuevo:^u ->^t)' que no se compila en VS2010. Me alegra saber que hay una manera más simple de hacer esto. – Daniel

+0

Curiosamente, el compilador solo admite restricciones de constructor explícitas de la forma 'nuevo: unidad -> 't' (que son directamente representables en metadatos .NET), pero aparentemente se puede usar una restricción de constructor más general _invocation expressions_ y dejar que el compilador infiera las restricciones . Definitivamente es un pequeño agujero en el sistema. – kvb

0

Utilizo métodos estáticos para este propósito. La razón es que a veces el constructor de objetos necesita dos argumentos tomados de diferentes fuentes, y mi enfoque le permite utilizar List.map2:

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

let result1 = List.map2 NumRange.Make values ranges 

Aplicación parcial no está prohibida, así:

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

si no le gusta usando id aquí, puede usar (fun x y -> x y) que es más legible.

1

Para dar una actualización sobre esto - F# 4.0 ha actualizado los constructores a funciones de primera clase, por lo que ahora se pueden usar en cualquier lugar donde se pueda utilizar una función o método.

Cuestiones relacionadas