2010-04-20 23 views
5

¿Cómo ML realiza la inferencia de tipos en la siguiente definición de función:Explicar ML inferencia de tipos a un programador de C++

let add a b = a + b 

¿Es como las plantillas de C++ donde ningún tipo de comprobación se realiza hasta el punto de instancias de plantilla después de que si el tipo admite las operaciones necesarias, la función funciona o se genera un error de compilación?

es decir, por ejemplo, la siguiente plantilla de función

template <typename NumType> 
NumType add(NumType a, NumType b) { 
    return a + b; 
} 

funcionará para

add<int>(23, 11); 

pero no funcionará para

add<ostream>(cout, fout); 

es lo que supongo es correcta o ¿La inferencia del tipo ML funciona de manera diferente?

PD: Perdón por mi pobre inglés; no es mi lengua materna

+1

¿Está preguntando sobre la inferencia de tipos o la verificación de tipos? – sepp2k

+0

inferencia. ¿Qué tipo de tipos se deducen de la definición de la función ML en mi ejemplo? –

Respuesta

5

le sugiero que eche un vistazo a este artículo: What is Hindley-Milner? (and why is it cool)

Aquí es el ejemplo más simple que utilizan para explicar la inferencia de tipos (que no es ML, pero la idea es la misma):

def foo(s: String) = s.length 
// note: no explicit types 
def bar(x, y) = foo(x) + y 

Solo mirando la definición de barra, podemos ver fácilmente que su tipo debe ser (String, Int) => Int. Eso es tipo de inferencia en pocas palabras. Lea el artículo completo para obtener más información y ejemplos.

No soy un experto en C++, pero creo que las plantillas son algo más parecido a la genericidad/parametricidad, que es algo diferente.

+0

Lo que no entiendo es por qué el tipo de 'a' y' b' en 'func diversión (a, b) = a + b' no se infiere de' real' (coma flotante) por ejemplo. ¿Eso es porque 'int' tiene prioridad sobre' real'? – ZhekaKozlov

4

ML utiliza Hindley-Milner type inference. En este caso simple, todo lo que tiene que hacer es mirar el cuerpo de la función y ver que usa + con los argumentos y lo devuelve. Por lo tanto, puede inferir que los argumentos deben ser del tipo de argumentos que + acepta (es decir, ints) y la función devuelve el tipo que devuelve + (también int). Por lo tanto, el tipo inferido de add es int -> int -> int.

Tenga en cuenta que en la LME (pero no CAML) + se define también para otros tipos de a un int, pero aún así se infiere int cuando hay múltiples posibilidades (es decir, la función add que ha definido no puede ser utilizado para agregar dos flotadores) .

5

Creo que intentar relacionar la inferencia de tipo ML con casi cualquier cosa en C++ es más probable que genere confusión que comprensión. C++ simplemente no tiene nada que se parezca mucho a la inferencia de tipo.

La única parte de C++ que no hace explícito el tipeo son las plantillas, pero (en su mayor parte) admiten la programación genérica. Una plantilla de función de C++ como la que has dado podría aplicarse igualmente a un conjunto ilimitado de tipos; solo por ejemplo, el código que tienes usa NumType como el parámetro de la plantilla, pero funcionaría con cadenas. Un solo programa podría instanciar su add para agregar dos cadenas en un lugar y dos números en otro lugar.

La inferencia de tipo ML no es para programación genérica.En C o C++, define explícitamente el tipo de un parámetro, y luego el compilador verifica que todo lo que intenta hacer con ese parámetro está permitido por ese tipo. ML invierte eso: mira las cosas que haces con el parámetro, y descubre qué tipo de tiene para que puedas hacer esas cosas. Si ha intentado hacer cosas que se contradicen entre sí, le dirá que no hay ningún tipo que pueda satisfacer las limitaciones.

Esto sería prácticamente imposible en C o C++, en gran parte debido a todas las conversiones de tipo implícito que están permitidas. Solo por ejemplo, si tengo algo como a + b en ML, puede concluir inmediatamente que a y b deben ser enteros, pero en C o C++, podrían ser casi cualquier combinación de entero o puntero o tipos de punto flotante (con la restricción que no pueden ambos ser punteros) o utilizan tipos definidos que sobrecargan operator+ (p. ej., std::string). En ML, encontrar tipos puede ser exponencial en el peor de los casos, pero casi siempre es bastante rápido. En C++, estimaría que es exponencial con mucha más frecuencia, y en muchos casos probablemente estaría poco restringido, por lo que una función determinada podría tener una cantidad de firmas diferentes.

+2

C++ 0x tiene inferencia de tipo local (como C# pero un poco más general) con la palabra clave 'auto'. Pero eso, por supuesto, está muy lejos de Hindley-Milner. Básicamente, solo funciona en el punto de declaración y solo si la variable se inicializa inmediatamente con una expresión constante. –

Cuestiones relacionadas