lunes, 24 de agosto de 2009

Covariancia y contravariancia (III)

Regla general

Estamos llegando a una regla más o menos universal que es: lo que se escribe desde fuera del tipo se hace contravariante, lo que se lee desde fuera del tipo se hace covariante.

En una función: Se pasan (escriben) argumentos y se devuelve (lee) el retorno. Las funciones son contravariantes en los argumentos y covariantes en el retorno.

Esto tiene que matizarse y veremos por qué en el siguiente apartado.

Menos por menos es más

Ahora vamos a hacer un esfuerzo mental para pensar en lo que ocurre cuando pasamos una función a otra función.

La función "total_sillas" tiene el siguiente tipo:

total_sillas ::  (S -> int) -> int

Esta función conoce de alguna manera todas las sillas de mi casa y usa la función que se le pasa de argumento (la S -> int) para obtener alguna propiedad numérica de estas sillas. Finalmente, retorna la suma total de estos números.

La función "total_muebles" es igual, pero trabaja con los muebles.

total_muebles :: (M -> int) -> int

Como propiedades numéricas vamos a usar estas dos funciones:

cuenta_patas :: S -> int

altura_mueble :: M -> int

Ahora vamos a ver si una se puede usar donde la otra o no.

total_muebles(altura_mueble) // OK, mismo tipo

total_sillas(altura_muebles)//Bien,las sillas tienen altura

total_sillas(cuenta_patas) //OK, mismo tipo

total_muebles(cuenta_patas) //Mal, hay muebles sin patas

Así que puedo usar "total_sillas" donde usaba "total_muebles", es decir:

 S                 <:   M

(S -> int) -> int  <:  (M -> int) -> int

Lo que significa que ¡es covariante! Esto es muy curioso porque los argumentos de una función eran contravariantes, pero los argumentos de los argumentos que serían contra-contravariantes son covariantes.

La moraleja a recordar es: La contravariancia es como el menos en la multiplicación, menos por menos es más. O sea, contravariante de contravariante es covariante.

Esto nos lleva a una regla muy usada en la teoría de tipos que es: Será covariante si está a la izquierda de un número par de "->" y contravariante en caso contrario. Esta regla se puede ver en el capítulo dedicado a la teoría de tipos del manual de las ciencias de la computación escrito por Cardelli. En la página 28.

Escribiré "cov" cuando sea covariante y "con" cuando sea contravariante en estos ejemplos:

con ->  con -> cov   (Se asocia por la derecha)

(cov -> con) -> cov

con-> (cov -> con) -> cov

(cov -> cov -> con) -> cov

((con -> cov) -> con) ->cov

En la siguiente parte de este serial veremos cómo afecta la mutabilidad a la variancia de tipos mediante el uso de punteros.

0 comentarios:

Publicar un comentario