usando tipos tipo ser referencia poo objeto genericos generico genericas generica debe crear clases clase generics f# constraints ref byref

tipos - usando generics c#



F#miembros restricciones+^ un byref parĂ¡metros (3)

Creo que también es un error, algo con restricciones de miembros y tipos byref. Puedo hacer una versión de reflexión un poco menos fea cambiando la firma de la restricción miembro:

let inline tryParse<''a when ''a : (static member TryParse : string -> ''a byref -> bool)> s = let args = [| s ; null |] if typeof<''a> .GetMethod("TryParse", [| typeof<string>; typeof< ^a>.MakeByRefType() |]) .Invoke(null, args) = box true then Some (args.[1] :?> ''a) else None

Este es muy cercano:

let inline tryParse< ^a when ^a: (static member TryParse: string -> ^a byref -> bool)> s = let mutable x = Unchecked.defaultof<''a> if (^a: (static member TryParse: string -> ^a byref -> bool) (s, &x)) then Some x else None

pero obtengo un error FS0421: la dirección de la variable ''x'' no se puede usar en este momento cuando intento compilarla.

Después de jugar un poco con las restricciones de miembros F #, la función de escribir y escribir es la siguiente:

let inline parse< ^a when ^a : (static member Parse: string -> ^a) > s = (^a: (static member Parse: string -> ^a) s)

Eso funciona perfectamente bien:

let xs = [ "123"; "456"; "999" ] |> List.map parse<int>

Estoy intentando escribir otras tryParse , que usa el método estático TryParse y ajusta el resultado del análisis en ''a option tipo de ''a option para una mejor compatibilidad en F #. Algo como esto no compila:

let inline tryParse s = let mutable x = Unchecked.defaultof< ^a> if (^a: (static member TryParse: string * ^a byref -> bool) (s, &x)) then Some x else None

El error es:

error FS0001: se esperaba que esta expresión tuviera el tipo byref <''a> pero aquí tiene el tipo '' a ref

F # ref -cells tampoco funciona:

let inline tryParse s = let x = ref Unchecked.defaultof< ^a> if (^a: (static member TryParse: string * ^a byref -> bool) (s, x)) then Some x else None

¿Qué estoy haciendo mal?


Esto compila pero aún no funciona como se esperaba:

let inline tryParse< ^a when ^a: (static member TryParse: string -> ^a ref -> bool) > s = let x = ref Unchecked.defaultof< ^a> match (^a: (static member TryParse: string -> ^a ref -> bool ) (s, x)) with | false -> None | true -> Some(!x) // returns [Some 0; Some 0; Some 0; null], so our tryParse is not retrieving the value from the ref let xs = [ "1"; "456"; "999"; "a" ] |> List.map tryParse<int>

en este caso específico, en lugar de usar el reflejo, simplemente recrearía TryParse de Parse en f #

let inline tryParse< ^a when ^a: (static member Parse: string -> ^a) > s = try Some(^a: (static member Parse: string -> ^a) s) with | exn -> None let xs = [ "1"; "456"; "999"; "a" ] |> List.map tryParse<int>


ACTUALIZAR

Esto parece estar arreglado en F # 3.0.

Respuesta anterior:

Estoy de acuerdo con el comentario de Stephen de que probablemente sea un error. Hay muchas limitaciones en los tipos byref, por lo que no me sorprende en particular que no jueguen bien con las restricciones de los miembros. Aquí hay una solución (fea) usando la reflexión:

type parseDel<''a> = delegate of string * ''a byref -> bool type Parser< ^a when ^a : (static member TryParse: string * ^a byref -> bool)> private ()= static let parser = System.Delegate.CreateDelegate(typeof<parseDel<''a>>, typeof<''a>.GetMethod("TryParse", [|typeof<string>; typeof<''a>.MakeByRefType()|])) :?> parseDel<''a> static member inline ParseDel = parser let inline tryParse (s:string) = let mutable x = Unchecked.defaultof< ^a> if Parser<_>.ParseDel.Invoke(s, &x) then Some x else None let one : int option = tryParse "1"