2011-05-05 7 views
7

Estoy intentando utilizar explicit member constraints en F #. La documentación dice "F # admite el conjunto completo de restricciones que admite el tiempo de ejecución de lenguaje común", pero si realmente compilo una clase con una restricción tan explícita, como la siguiente, obtengo un error bastante exótico.F # restricciones explícitas de miembro: La variable de tipo^T no se puede generalizar porque escaparía de su alcance

type MyType<'T when ^T: (static member (+) : ^T * ^T -> ^T)> = 
    member this.F a b = a + b 

informa

FS0670 ​​de error: Este código no es lo suficientemente genérico. La variable de tipo^T cuando^T: (miembro estático (+):^T *^T ->^T) no podría generalizarse porque escaparía a su alcance.

Y lo informa en el sitio de definición member this.F. ¿Qué significa esto? ¿Cuál es el alcance relevante?

Hay una serie de enfoques compatibles con el lenguaje para hacer este tipo de trabajo. Se puede encontrar una buena exploración en here on StackOverflow, pero no he visto una explicación clara de por qué esta restricción genérica particular no puede 'escapar'.

+0

Casi nunca es necesario especificar las restricciones de los miembros explícitamente. El compilador lo infiere (como en el ejemplo de wmeyer). – Daniel

+0

La idea clave es que las restricciones explícitas de los miembros son una característica del compilador, no del tiempo de ejecución. Los documentos son correctos: F # admite todas las restricciones de CLR, pero el compilador admite aún más. – Daniel

Respuesta

1

F # especificación:

Un tipo de la forma^ident es un estáticamente resuelto tipo variable. Una variable de inferencia de tipo nuevo es creada y agregada al entorno de inferencia de tipo (ver §14.6). Esta variable tipo se etiqueta con un atributo que indica que no se puede generalizar excepto en inline definiciones (ver §14.7), e igualmente cualquier variable de tipo con el que es equiparado a través de una ecuación de inferencia tipo de manera similar no puede ser generalizado restricciones

http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html

8

miembros deben resolverse de forma estática parámetros de tipo. Pero los parámetros de tipo resueltos estáticamente no están permitidos en los tipos (como en su ejemplo), solo para las funciones en línea y los métodos en línea.

El problema subyacente es probablemente que los tipos como un todo no pueden estar en línea.

Consulte también: http://msdn.microsoft.com/en-us/library/dd548046.aspx

Si utiliza un miembro en línea como esta:

type MyType() = 
    member inline this.F a b = a + b 

los tipos de A y B automáticamente será constreñido correctamente.

3

Usted necesidad de marcar el miembro inline (y añadir anotaciones de tipo si desea forzar los argumentos para ser de tipo ^T):

type MyType<'T when ^T: (static member (+) : ^T * ^T -> ^T)>() = 
    member inline this.F (a:^T) (b:^T) = a + b 

También he añadido un constructor, para que pueda realmente llamar al método:

MyType().F 1 2 

Como otros han señalado, rara vez es necesario escribir las limitaciones miembro explícito a mano, ya que por lo general se desprenderán. Además, en este caso no hay ninguna razón para poner la restricción en el tipo en lugar del método, y tener un tipo parametrizado por una variable de tipo resuelta estáticamente no es idiomático.

Cuestiones relacionadas