Thursday, January 14, 2010

Diversión con tipos de datos algebraícos

Los tipos de datos algebraicos o ADT (por sus siglas en inglés: Algebraic Data Types) son una de las características más interesante de los "nuevos" lenguajes funcionales, y por nuevos quiero decir de la época de SML. Lo simpático de los ADTs es que reunen en un solo concepto lo que en otros lenguajes serían enumeraciones, estructuras y uniones.

Por ejemplo, las enumeraciones. Una enumeración es básicamente un conjunto de constantes utilizados para representar los posibles valores de un tipo dado. Para representar los días de la semana en C, utilizaríamos:
enum diasemana {
    DOMINGO, LUNES, MARTES, MIERCOLES,
    JUEVES, VIERNES, SABADO
};
Solo que en C, los enums son azúcar sintáctica, es una forma abreviada de definir un grupo de constantes. diasemana no es de ninguna forma un tipo de datos, son simplemente enteros.

En Haskell, el código anterior sería:
data Diasemana = Domingo | Lunes | Martes | Miercoles
    | Jueves | Viernes | Sabado
la diferencia está en que, Diasemana si es un tipo de datos. Los valores de tipo Diasemana no son equivalentes a los enteros y no pueden mezclarse.

Otro tipo de datos popular son las estructuras, que no son mas que un conjunto ordenado de valores de (posiblemente) diferentes tipos. En C una estructura se define del siguiente modo:
typedef struct student_type {
    char nombre[20];
    char apellido[20];
    int edad; } persona;
en Haskell sería:
data Persona = Persona String String Int

En Haskell, el tipo Persona esta formado por la etiqueta 'Persona' (llamado constructor de datos) y seguido por tres valores: dos strings y un entero.

Finalmente están las uniones. Una unión es una estructura de datos cuyos valores pueden pertenecer a dos o más tipos diferentes. Por ejemplo, en C:
typedef struct {float real, imaginario; } cartesiano;
typedef struct {float modulo, angulo; } polar;
union {
    cartesiano c;
    polar p;
} complejo;
En Haskell:
data Complejo = Cartesiano Float Float | Polar Float Float
Como se ve, usando solo los ADT se logra lo que en otros lenguajes requiere tres tipos diferentes de estructura de datos. Y no solo eso, sino que el resultado es más compacto.

Otra ventaja de los ADT viene, al menos para mí, del aspecto sicológico. Mientras que en C, fiel a su tradición de eficiencia y cercanía a la "maquina desnuda", estas estructuras de datos definen alineamientos en memoria, los ADTs ofrecen una definición más abstracta. Leer un ADT es leer las estructuras de datos del problema en su propio lenguaje. Leer un enum, union o struct de C, es leer la traducción de las estructuras de datos al lenguaje del computador.

No comments: