Wednesday, December 30, 2009

Tipos polimorficos en Haskell

Una vez pasado el shock inicial, la información sobre los tipos de las expresiones en haskell pueden ser realmente útiles. Si revisas una librería en haskell y ves la firma de las funciones, prácticamente sabrás todo lo que necesitas conocer sobre las mismas.

Este hecho siempre me sorprendió. Ver la firma de una función en C no ofrece la misma cantidad de información, incluso para alguien como yo, más familiarizado con C que con Haskell. Y desde luego, los lenguajes de script no ofrecen ninguna garantía sobre los parametros que reciben sus funciones.

Pero, por que? Como es que la firma de una función en Haskell ofrece tanta información? No entendía la respuesta hasta leer Real World Haskell. Por ejemplo, la siguiente declaración:

qsort :: Ord a => [a] -> [a]

Nos dice que qsort es una función polimorfica que toma una lista de elementos del tipo a y devuelve una lista del mismo tipo. El único dato que conocemos sobre el tipo a es que es de la clase Ord, es decir que sobre él están definidas las comparaciones de igualdad, mayor que, menor que, etc.

Lo interesante del caso, es que cuando digo conocemos, me refiero no solo a las personas que leen el código, sino también a la función. La función qsort no sabe algo sobre a que nosotros ignoremos. Cualquier función definida sobre a distinta de la clase Ord es inaccesible a qsort. Es decir, sea lo que sea que qsort haga, solo puede comparar los elementos de [a]. Y dado que las funciones en Haskell son puras, no tiene acceso a variables externas, por lo que la lista resultante depende solo de la lista de entrada.

Esto reduce enormemente las posibilidades de qsort. Sentido común en la elección del nombre por parte del autor y una linea de documentación nos dirá el resto de lo que necesitamos saber: qsort devuelve una lista con los elementos de su argumento ordenados.

Otro ejemplo es el siguiente:

mistery :: (a -> b) -> [a] -> [b]

El nombre de la función ha sido ofuscado deliberadamente. Para quienes no conocen Haskell, el primer argumento (a -> b) es una función que toma argumentos de tipo a y devuelve elementos del tipo b. De nuevo, como no sabemos absolutamente nada sobre los tipos a y b, mistery no puede usar otra información más que la dada para llevar a cabo su cometido.

Puedes adivinar que hace mistery?