En los lenguajes de programación con disciplina de tipos,
cada tipo representa una colección de valores (datos) similares. Una función
cuyo tipo sea A1 -> ... An -> espera n parámetros con tipos A1, ... An y
devuelve un resultado de tipo R. El conocer los tipos de las funciones ayuda a
documentar los programas y a evitar errores en tiempo de ejecución.
Disciplina estática de tipos: Los programas bien tipados se
pueden reconocer en tiempo de compilación, un programa bien tipado se puede
utilizar sin efectuar comprobaciones de tipo en tiempo de ejecución. Estando
garantizado que no se producirán errores de tipo durante el cómputo.
Clases de errores
Al escribir una función se pueden cometer
errores. El intérprete puede avisar de algunos errores. Si la definición de una
función no es correcta, el intérprete da un mensaje en el momento de analizar
la definición. Por ejemplo, la siguiente definición contiene un error:
esCero x = x=0
El segundo = tenía que ser el operador
== (= significa ‘se define como’ y == significa ‘es igual a’). Al analizar esta
definición el intérprete dice:
Reading script file "nuevo":
Parsing...............
ERROR "nuevo" (line 18): Syntax error in input (unexpected
‘=’)
El intérprete encuentra los errores de sintaxis en el primer paso del análisis:
el análisis sintáctico (en inglés: parsing). Otros errores pueden ser un paréntesis
izquierdo sin su paréntesis derecho correspondiente, o el uso de palabras
reservadas (como where) en lugares en los que no se permiten. Además de los
errores de sintaxis, existen otros errores que el intérprete puede encontrar.
Una posibilidad es usar una función que no está definida. Por ejemplo, con:
fac x =
producto [1..x]
el int´erprete dice:
Reading script file "nuevo":
Parsing..............
Dependency
analysis....................................
ERROR "nuevo" (line 19): Undefined variable
"producto"
Estos errores se encuentran
durante el segundo paso: el análisis de dependencia (dependency analysis). El
siguiente obstáculo en el análisis es la comprobación de los tipos (type
checking). Por ejemplo, funciones que operan sobre números no pueden ser usadas
con valores booleanos y tampoco con listas. Con la expresión 1+True en la
definición de una función el intérprete dice:
Reading script file "nuevo":
Parsing...............
Dependency analysis...
Type checking......
ERROR "nuevo" (line 22): Type error in application
*** expression : 1 +
True
*** term : 1
*** type :
Int
*** does not match : Bool
La subexpresón (term) 1 tiene el
tipo Int (entero). No se puede sumar tal valor a True, que es de tipo Bool.
Otros errores de tipado se producen si se
aplica la función length a algo diferente de una lista, como en length 3:
ERROR: Type error in application
*** expression : length 3
*** term : 1
*** type : Int
*** does not match : [a]
Sólamente si no existen errores de tipado en el programa, el intérprete
ejecuta el cuarto paso (generación de código).
El intérprete da todos los mensajes de error en el momento de analizar
una función. En algunos otros lenguajes se comprueba el tipado en el momento en
que se llama a una función. En este caso nunca se está seguro si existen
errores de tipado o no. Si el intérprete de Gofer no da mensajes de error, se
puede estar seguro de que no existen errores de tipado.
Pero, si el intérprete de Gofer no da mensajes de error, es posible todavía
encontrar errores en el programa. Si se pone (por ejemplo) en la definición de
la función suma el signo menos en vez del signo más, el programa no funciona
bien, pero el intérprete no lo sabe. Estos errores, ‘errores lógicos’, son los más
difíciles de encontrar.
Expresiones de tipo
El tipo de una expresión se puede determinar con el comando del
intérprete: type seguido de la expresión de la que se quiere conocer el tipo.
Por ejemplo:
? :type 3+4
3 + 4 :: Int
El símbolo: significa: ‘es del
tipo’. La expresión no se evalúa con el comando: type, solamente se determina
el tipo.
Existen cuatro tipos estándar:
• Int: el tipo de los enteros;
• Float: el tipo de los números de punto flotante (floating-point);
• Bool: el tipo de los valores booleanos: True y False; pág. 49
• Char: el tipo de los caracteres (se tratará en el párrafo 3.2.2).
También las funciones tienen un tipo. El tipo de una función está
determinado por el tipo del parámetro y el tipo del resultado. Por ejemplo, el
tipo de la función sum es:
? :type sum
sum :: [Int] -> Int
La función sum opera sobre listas de enteros y como resultado devuelve
un solo entero. El símbolo -> en el tipo de la función representa una flecha
(→). Otros ejemplos de tipos de funciones son:
sqrt :: Float -> Float
even :: Int -> Bool
sums :: [Int] -> [Int]
Se suele decir: “even tiene el tipo de int a bool”.
Polimorfismo
Para algunas funciones sobre listas no interesa el tipo de los elementos
de la lista. La función estándar length puede determinar el tamaño de una lista
de enteros, pero también de una lista de valores booleanos, y –por qué no– de
una lista de funciones. El tipo de la función length se define como sigue:
length :: [a] -> Int
Este tipo indica que esta función se aplica sobre una lista, pero que el
tipo de los elementos de esta lista no importa. Este tipo se indica por medio
de una variable de tipo, en el ejemplo se utiliza la letra a. Variables de tipo
se escriben con una letra minúscula, al contrario que los tipos fijos como Int
y Bool. La función head, que devuelve el primer elemento de una lista, tiene el
tipo:
head :: [a] -> a
Esta función se aplica también a listas, sin que importe cual sea el
tipo de los elementos. Pero su resultado es del tipo de los elementos de la
lista (es el primer elemento de la lista). Por tanto, se usa para el tipo del
resultado la misma variable que para el tipo de los elementos de la lista. Un
tipo que contiene variables de tipo, se llama tipo polimórfico. Las funciones
con un tipo polimórfico se llaman funciones polimórficas. El fenómeno en si se
llama polimorfismo. Las funciones polimórficas, como length y head, tienen en
común que usan solamente la estructura de una lista. Una función no polimórfica
como sum, usa también propiedades de los elementos de la lista (como la
posibilidad de sumarlos, etc.).
Fokker, J. (1996). Programacion
Lógica y funcional. Madrid: Copyright.
No hay comentarios:
Publicar un comentario