Una Introducción agradable a Haskell
anterior siguiente
inicio
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.
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.
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)
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