Una Introducción agradable a Haskell
anterior siguiente inicio


12  Errores de tipos más comunes

Esta sección muestra una descripción intuitiva de algunos problemas comunes que los principiantes suelen tener cuando se enfrentan al sistema de tipos de Haskell.

12.1  Polimorfismo restringido en construcciones let

Cualquier lenguaje que usa el sistema de tipos de Hindley-Milner tiene el llamado polimorfismo restringido en construcciones let, porque los identificadores no ligados por las cláusulas let o where (o en el nivel superior de un módulo) están limitados con respecto a su polimorfismo. En particular, una función lambda-bound (es decir, pasada como argumento a otra función) no puede ser instanciada de dos diferentes maneras. Por ejemplo, este programa es ilegal:

let f g  =  (g [], g 'a')                       -- expresion mal tipada
in f (\x->x)

porque g, está ligada por una lambda abstracción cuyo tipo principal es a->a, y se usa dentro de f de dos formas diferentes con tipos [a]->[a] la una y Char->Char la otra.

12.2  Sobrecarga Numérica

Es fácil olvidarse de que los números están sobrecargados, y no hay promoción implícita a los distintos tipos numéricos, como en muchos otros lenguajes. Hay expresiones numéricas genéricas que a veces no son tan genéricas. Un error numérico común es el siguiente:

average xs              =  sum xs / length xs           -- Mal!

(/)
requiere argumentos fraccionarios, pero el resultado de length es Integer. La discordancia del tipo se debe corregir con una promoción explícita:

average                 :: (Fractional a) => [a] -> a
average xs              =  sum xs / fromIntegral (length xs)

12.3  La Restricción Monomórfica

El sistema de tipos de Haskell contiene una restricción relacionada con las clases de tipos que no se encuentra en sistemas ordinarios de tipos basados en el de Hindley-Milner: la restricción del monomorfismo. La razón de esta restricción está relacionada con una ambigüedad sutil del tipo y se explica en profundidad en el informe (§4.5.5). Una explicación más simple es la siguiente:

La restricción del monomorfismo dice que cualquier identificador enlazado a través de un patrón (ligaduras a un solo identificador), y que no tiene ninguna declaración explícita de tipo, debe ser monomórfica. Un identificador es monomórfico si o bien no está sobrecargado, o lo está pero se utiliza a lo sumo de una forma sobrecargada y no se exporta.

Las violaciones de esta restricción dan lugar a un error de tipo estático. La manera más simple de evitar el problema es proporcionar una declaración explícita del tipo. Observe que cualquier declaración de tipo valdrá (siempre que el tipo sea correcto).

Una violación común de la restricción sucede con las definiciones de funciones de orden superior, como en esta definición de sum del Standard Preluder:

sum                     =  foldl (+) 0

Como se ve, esto causaría un error de tipo estático. Podemos resolver el problema agregando la declaración de tipo:

sum                     :: (Num a) => [a] -> a

Obsérvese que no se habría presentado este problema si hubiesemos escrito:

sum xs                  =  foldl (+) 0 xs

porque la restricción se aplica solamente a los patrones.


Una Introducción agradable a Haskell
anterior siguiente inicio