Está en la página 1de 91

Instituto tecnolgico superior de zongolica

ANTOLOGA DE
PROGRAMACIN
LGICA Y FUNCIONAL

M.S.C. Martn Contreras de la Cruz

SEMESTRE AGO2014 ENE2015

PROPSITO DEL CURSO


La asignatura de Programacin Lgica y Funcional aporta al perfil del Ingeniero en
Sistemas Computacionales la capacidad de desarrollar habilidades para la
generacin de soluciones automatizadas basadas en lenguajes de inteligencia
artificial, considerando el entorno y la aplicacin de diversas tcnicas, herramientas
y conocimientos.

Los programas para computadora actualmente son fundamentales en muchas


reas del ser humano, debido a que se usan para resolver diversos problemas en
la ciencia, la industria y los negocios. Para cubrir estas necesidades, se han
desarrollado lenguajes de programacin dentro de la inteligencia artificial. El
Ingeniero en Sistemas Computacionales contribuir, aplicando estos conocimientos
para la solucin de problemas a travs de la programacin lgica y funcional, con
una conciencia tica y de respeto al medio ambiente.

Programacin Lgica y Funcional, es una asignatura que requiere tener


conocimientos esenciales acerca de los lenguajes lgicos y funcionales de la
inteligencia artificial, incluyendo la metodologa y los aspectos relativos a la
codificacin, con el fin de ampliar el conocimiento de tecnologas alternativas para
el desarrollo de sistemas automatizados y la implementacin de agentes
inteligentes.

CONTENIDO
UNIDAD 1.Conceptos Fundamentales .............................. 6
1.1. Estilos de programacin ........................................................................... 8
1.2. Evaluacin de expresiones. .................................................................... 12
1.3. Definicin de funciones. ......................................................................... 15
1.4. Disciplina de tipos. .................................................................................. 17
1.5. Tipos de datos ......................................................................................... 18
UNIDAD 2. Programacin Funcional .............................. 22
2.1. El tipo de datos ........................................................................................ 24
2.2. Funciones ................................................................................................ 34
2.3. Intervalos ................................................................................................. 35
2.4. Operadores .............................................................................................. 36
2.5. Aplicaciones de las listas ....................................................................... 37
2.6. rboles ..................................................................................................... 40
UNIDAD 3. Evaluacin perezosa.................................. 42
3.1. Estrategias de evaluacin perezosa....................................................... 44
3.2. Tcnicas de programacin funcional perezosa..................................... 47
UNIDAD 4. Fundamentos de la programacin lgica.................. 50
4.1. Repaso de lgica de primer orden ......................................................... 52
4.2. Unificacin y Resolucin ........................................................................ 55
4.3. Clusulas de Horn. Resolucin SLD ...................................................... 56
4.4. Programacin lgica con clusulas de Horn ......................................... 62
4.5. Consulta de una base de clusulas ....................................................... 63
4.6. Representacin causada del conocimiento........................................... 63
4.7. Consulta de una base de clusulas ....................................................... 70
4.8. Espacios de bsqueda ............................................................................ 70
4.9. Programacin lgica con nmeros, listas y rboles. ............................ 74
BIBLIOGRAFIA ............................................... 91

RED CONCEPTUAL DEL CURSO

Conceptos Fundamentales

Programacin Funcional
Programacin Lgica y
Funcional

Evaluacin Perezosa

Fundamentos de Programacin Lgica

COMPETENCIAS A ALCANZAR EN EL CURSO


Al trmino del curso el participante:
Conocer los principios lgicos y funcionales de la programacin para
identificarlos y aplicarlos en la resolucin de problemas a travs del diseo de
agentes inteligentes.
1. Competencias instrumentales
Capacidad de anlisis y sntesis.
Capacidad de organizar y planificar.
Conocimientos bsicos de la carrera
Comunicacin oral y escrita.
Manejo de todos los recursos que proporciona la computadora.
Habilidad para buscar y analizar informacin proveniente de fuentes
diversas.
Solucin de problemas.
Toma de decisiones.
2. Competencias interpersonales
Capacidad crtica y autocrtica.
Trabajo en equipo.
Habilidades interpersonales.
3. Competencias sistmicas
Capacidad de aplicar los conocimientos en la prctica.
Habilidades de investigacin.
Capacidad de aprender.
Capacidad de generar nuevas ideas
(creatividad).
Habilidad para trabajar en forma autnoma.
Bsqueda del logro.

UNIDAD 1.Conceptos Fundamentales


RED CONCEPTUAL

Estilos de Programacin

Evaluacin de Expresiones

Conceptos
fundamentales

Definicin de funciones

Disciplina de Tipos

Tipo de Datos

Competencia General de la Unidad:

Identificar los paradigmas y lenguajes de programacin representativa.

Visualizar los diversos estilos de la programacin.


Identificar los conceptos bsicos de la programacin representativa.
Reconocer las caractersticas de la programacin representativa.
Investigar, al menos un lenguaje de programacin representativa.
Realizar mapa conceptual de los paradigmas y lenguajes de la
programacin representativa.

1.1. Estilos de programacin

A continuacin se muestra un mapa conceptual donde se presenta una sntesis


sobre los estilos de programacin

Estilo de programacin (tambin llamado estndares de cdigo o convencin de


cdigo) es un trmino que describe convenciones para escribir cdigo fuente en
ciertos lenguajes de programacin.
El estilo de programacin es frecuentemente dependiente del lenguaje de
programacin que se haya elegido para escribir. Por ejemplo el estilo del lenguaje
de programacin C variar con respecto al del lenguaje BASIC.
Caractersticas del estilo
El buen estilo, al tratarse de algo subjetivo, es difcil de categorizar concretamente;
con todo, existen un nmero de caractersticas generales. Con el advenimiento de
software que da formato al cdigo fuente de forma automtica, el foco en cmo
ste debe de ser escrito debe evolucionar de forma ms amplia a la eleccin de
nombres, lgica y otras tcnicas. Desde un punto de vista prctico, el uso de un
computador para dar formato al cdigo fuente ahorra tiempo, y es posible forzar el
uso de estndares a nivel de una compaa completa sin debates religiosos.
Nombres de variable apropiadas
Una piedra clave para un buen estilo es la eleccin apropiada de nombres de
variable. Variables pobremente nombradas dificultan la lectura del cdigo fuente y
su comprensin.
Como ejemplo, considrese el siguiente extracto de pseudocdigo:
get a b c
if a < 24 and b < 60 and c < 60
return true
else
return false
Debido a la eleccin de nombres de variable, es difcil darse cuenta de la funcin
del cdigo. Comprese ahora con la siguiente versin:
get horas minutos segundos
if horas < 24 and minutos < 60 and segundos < 60
return true
else
return false
La intencin el cdigo es ahora ms sencilla de discernir, "dado una hora en 24
horas, se devolver true si es vlida y false si no".

Estilo de identacin
Estilo de indentacin, en lenguajes de programacin que usan llaves para identar
o delimitar bloques lgicos de cdigo, como por ejemplo C, es tambin un punto
clave el buen estilo. Usando un estilo lgico y consistente hace el cdigo de uno
ms legible. Comprese:
if(horas < 24 && minutos < 60 && segundos < 60){
return true;
}else{
return false;
}
o bien:

if(horas < 24 && minutos < 60 && segundos < 60)


{
return true;
}
else
{
return false;
}
con algo como:
if(horas<24&&minutos<60&&segundos<60){return true;}
else{return false;}
Los primeros dos ejemplos son mucho ms fciles de leer porque estn bien
indentados, y los bloques lgicos de cdigo se agrupan y se representan juntos de
forma ms clara.

Valores booleanos en estructuras de decisin


Algunos programadores piensan que las estructuras de decisin como las
anteriores, donde el resultado de la decisin es meramente una computacin de
un valor booleano, son demasiado prolijos e incluso propensos al error. Prefieren
hacer la decisin en la computacin por s mismo, como esto:

return horas < 12 && minutos < 60 && segundos < 60;
La diferencia es, con frecuencia, puramente estilstica y sintctica, ya que los
compiladores modernos producirn cdigo objeto idntico en las dos formas.
Bucles y estructuras de control
El uso de estructuras de control lgicas para bucles tambin es parte de un buen
estilo de programacin. Ayuda a alguien que est leyendo el cdigo a entender la
secuencia de ejecucin (en programacin imperativa). Por ejemplo, el siguiente
pseudocdigo:
cuenta = 0
while cuenta < 5
print cuenta * 2
cuenta = cuenta + 1
endwhile
El extracto anterior cumple con las dos recomendaciones de estilo anteriores, pero
el siguiente uso de la construccin for hace el cdigo mucho ms fcil de leer:

for cuenta = 0, cuenta < 5, cuenta=cuenta+1


print cuenta * 2

En muchos lenguajes, el patrn frecuentemente usado "por cada elemento en un


rango" puede ser acortado a:
for cuenta = 0 to 5
print cuenta * 2

Espaciado
Los lenguajes de formato libre ignoran frecuentemente los espacios en blanco. El
buen uso del espaciado en la disposicin del cdigo de uno es, por tanto,
considerado un buen estilo de programacin.
Comprese el siguiente extracto de cdigo C:

int cuenta;
for(cuenta=0;cuenta<10;cuenta++){printf("%d",cuenta*cuenta+cu
enta);}
con:
int cuenta;
for (cuenta = 0; cuenta < 10; cuenta++)
{
printf("%d", cuenta * cuenta + cuenta);
}
En los lenguajes de programacin de la familia C se recomienda tambin evitar el
uso de caracteres tabulador en medio de una lnea, ya que diferentes editores de
textos muestran su anchura de forma diferente.

1.2. Evaluacin de expresiones.

QUE SON LAS EXPRESIONES?

Son el mtodo fundamental que tiene el programador de expresar computaciones.

Las expresiones estn compuestas de operadores, operandos, parntesis y llamadas a


funciones. Los operadores pueden ser:

Unarios: Cuando tan solo tienen un operando. Son operadores prefijos.

Binarios: 2 Operandos. Son operadores infijos.

Ternarios: 3 operandos.

ORDEN DE LA EVALUACIN DE LOS OPERADORES.

El orden en que se evalan los operandos viene dado por unas reglas:

Reglas de procedencia

Reglas de asociatividad

Uso de parntesis

EVALUACIN DE EXPRESIONES
Toda expresin regresa un valor. Si hay ms de un operador, se evalan primero operadores
mayor precedencia, en caso de empate, se aplica regla asociatividad
Para evaluar una expresin no hay que hacer nada del otro mundo, pues es bien sencillo.
Slo hay que saber sumar, restar, si un nmero es mayor que otro
Hay tres reglas de prioridad a seguir para evaluar una expresin:

Primero, los parntesis (si tiene)


Despus, seguir el orden de prioridad de operadores
Por ltimo, si aparecen dos o ms operadores iguales, se evalan de izquierda a
derecha.

Las expresiones son secuencias de constantes y/o variables separadas por operadores
vlidos.
Se puede construir una expresin vlida por medio de :
1. Una sola constante o variable, la cual puede estar precedida por un signo + .
2. Una secuencia de trminos (constantes, variables, funciones) separados por operadores.
Adems debe considerarse que:
Toda variable utilizada en una expresin debe tener un valor almacenado para que la
expresin, al ser evaluada, d como resultado un valor.
Cualquier constante o variable puede ser reemplazada por una llamada a una funcin.
Como en las expresiones matemticas, una expresin en Pascal se evala de acuerdo a la
precedencia de operadores
JERARQUA DE OPERADORES
El orden general de evaluacin de los operadores de una expresin va de izquierda a
derecha, con la excepcin de las asignaciones que lo hacen de derecha a izquierda.
Podemos seguir las siguientes tres reglas de evaluacin de expresiones:
(Regla 1) En todas las expresiones se evalan primero las expresiones de los parntesis ms
anidados (interiores unos a otros); y stos modifican la prioridad segn la cantidad de stos,
los cuales tienen que estar balanceados (el mismo nmero de parntesis que abren debe ser
igual al nmero de los parntesis que cierran).

(Regla 2) Todas las expresiones se evalan tomando en cuenta la jerarqua de los


operadores.
(Regla 3) Todas las expresiones se evalan de izquierda a derecha.
Tabla de evaluacin de C++

Tabla de evaluacin de Java

1.3. Definicin de funciones.

Un problema complejo se puede dividir en pequeos subproblemas mas sencillos. Estos


subproblemas se conocen como Mdulos y su complementacion en un lenguaje se llama
subprograma (procedimientos y funciones).
Un subprograma realiza las mismas acciones que un programa, sin embargo, un
subprograma lo utiliza solamente un programa para un propsito especifico.
Un subprograma recibe datos de un programa y le devuelve resultados (el programa
llama o invoca al subprograma, este ejecuta una tarea especifica y devuelve el
control al programa que lo llamo).
Funcin: Una funcin en matemticas, es una operacin que toma un o mas valores
(argumentos) y devuelve un resultado (valor de la funcin para los argumentos dados). Por
ejemplo:
F(X) = X / (1+X2)
Donde:
F .. Nombre de la funcin

X . Es el argumento (tambin conocido como parmetro formal)


Definicin de funciones: Una definicin de funcin se presenta de la siguiente manera:
Funcin nombre_funcion(p1, p2, , pn)
Inicio
Bloque de instrucciones
Fin
Donde:
Funcin Es la palabra clave que nos indica una definicin de funcin.
Nombre_funcion Es el identificador con el cual se reconoce a la funcin en el
cuerpo del algoritmo principal.
p1,p2,,pn Es el grupo de parmetros que define a la funcin.
Llamado a una funcin
Cuando definimos una funcin solo le indicamos al algoritmo que esta funcin existe, pero
una definicin de funcin no implica la realizacin de las instrucciones que la constituyen.
Para hacer uso de una funcin, el algoritmo principal la debe llamar. Por ejemplo:
Funcin F(X)
Inicio
F = X /(1 + X^2)
Fin
Inicio
Imprimir Este es el algoritmo principal
Leer N
R = F(N) llamado de la funcin
Imprimir El resultado de la funcin es:,R
Fin

1.4. Disciplina de tipos.


Los tipos se infieren, es decir se comprueban, de forma esttica, en tiempo de
compilacin.
En los lenguajes de programacin con disciplina de tipos, cada tipo representa una
coleccin de valores o datos similares. El conocer los tipos de las funciones ayuda a
documentar los programas y evitar errores en tiempo de ejecucin.
Un lenguaje tiene disciplina de tipos si los errores de tipos se detectan siempre es
necesario determinar los tipos de todos los operandos, ya sea en tiempo de compilacin o
de ejecucin

Pascal

Cercano a tener disciplina de tipos pero no realiza comprobacin de tipos en los registros
variantes (incluso puede omitirse la etiqueta discriminatoria en dichos registros)

Ada

Resuelve el problema de los registros variantes realizando comprobacin dinmica de


tipos (slo en este caso)
Tiene una funcin de biblioteca que permite extraer un valor de una variable de cualquier
tipo (como una cadena de bits) y usarlo como un tipo diferente (no es una conversin de
tipos) se trata de una suspensin temporal de la comprobacin de tipos

No tiene disciplina de tipos por:


No se realiza comprobacin de tipos sobre las uniones
Permite funciones con parmetros sobre los que no se realiza comprobacin de tipos

Java

Tiene disciplina de tipos (no hay uniones)

ML y Haskell

Poseen disciplina de tipos

Los tipos de los parmetros de las funciones (y de estas mismas) se conocen en tiempo de
compilacin (ya sea por declaracin del usuario o por inferencia de tipos)
Haskell y otros lenguajes funcionales utilizan el sistema de tipos de Milner, que tiene dos
caractersticas fundamentales:

Disciplina esttica de tipos: Los programas bien tipados se pueden conocer en


tiempo de compilacin. Un programa bien tipado se puede utilizar sin efectuar
comprobaciones de tipo en tiempo de ejecucin, estando garantizado que no se
producirn errores de tipo durante el computo.
Polimorfismo: Permite que una misma funcin se pueda aplicar a parmetros de
diferentes tipos, dependiendo del contexto en el que la funcin se utilice.

1.5. Tipos de datos

Todos los datos tienen un tipo asociado con ellos. Un dato puede ser un simple carcter, tal
como `b, un valor entero tal como 35. El tipo de dato determina la naturaleza del conjunto
de valores que puede tomar una variable.

Numricos
Simples Lgicos
Alfanumricos (string)
Tipos de datos Arreglos (Vectores, Matrices)
Estructurados Registros (Def. por el Archivos usuario) Apuntadores

Tipos de Datos Simples

Datos Numricos: Permiten representar valores escalares de forma numrica, esto


incluye a los nmeros enteros y los reales. Este tipo de datos permiten realizar
operaciones aritmticas comunes.
Datos Lgicos: Son aquellos que solo pueden tener dos valores (cierto o falso) ya
que representan el resultado de una comparacin entre otros datos (numricos o
alfanumricos).
Datos Alfanumricos (String): Es una secuencia de caracteres alfanumricos que
permiten representar valores identificables de forma descriptiva, esto incluye
nombres de personas, direcciones, etc. Es posible representar nmeros como
alfanumricos, pero estos pierden su propiedad matemtica, es decir no es posible
hacer operaciones con ellos. Este tipo de datos se representan encerrados entre
comillas

En Haskell nos encontramos con diferentes tipos simples como:

Int
Integer
Char
Bool

Lgicamente podemos construir listas, tuplas y funciones con esos tipos de datos. Otro tipo
que tenemos presente en Haskell es el tipo polimrfico. As podemos construir estructuras y
funciones polimrficas.
Dentro de las caractersticas de los tipos de Haskell podemos deducir que cada expresin
tiene un nico tipo principal y que ese tipo principal se puede deducir automticamente.
Adems, Haskell incorpora las funciones sobrecargadas que se pueden aplicar sobre varios
tipos pero no sobre todos los tipos. Para ello se dispone de una jerarqua de clases de tipos
con operadores y funciones sobrecargadas como:

Num: Tipos numricos.


Eq: Tipos que se pueden comparar.
Ord: Tipos que se pueden ordenar.

En la siguiente figura podemos encontrar un diagrama sobre la jerarqua de clases:

RESUMEN
El manejo de estndares y recomendaciones de programacin facilitaran al
programador la documentacin y seguimiento de sus proyectos an con el paso
del tiempo.
Mejorar el mantenimiento del software y permitir que el cdigo pueda ser ledo
por cualquier persona de la empresa que conozca los estndares de codificacin.
Es necesario indicar que las recomendaciones son exactamente mejores

apreciaciones de la experiencia de trabajo que pueden tomarse y adaptarse a las


necesidades de los nuevos paradigmas de la programacin.

UNIDAD 2. Programacin Funcional


RED CONCEPTUAL

El tipo de datos

Funciones

Intervalos

Programacin
Funcional
Operadores

Aplicaciones de las listas

rboles

Competencia General de la Unidad:


Conocer los principales puntos fuertes y debilidades del paradigma de
programacin funcional
Identificar los elementos de la programacin funcional.
Aplicar la programacin funcional en la resolucin de problemas reales.
Disear herramientas alternativas y complementarias de programacin.
Actividades de Aprendizaje

Identificar los conceptos bsicos de la programacin funcional.


Describir las caractersticas de la programacin funcional.
Reconocer la estructura y elementos de la programacin funcional.
Investigar; al menos, un lenguaje de programacin representativa diferente
al establecido para la materia.
Realizar mapa conceptual de los lenguajes de la programacin funcional
vistos en la materia.

2.1. El tipo de datos


Valores, Tipos, y otras Golosinas
Puesto que Haskell es un lenguaje funcional puro, todos los cmputos vienen descritos a
travs de la evaluacin de expresiones (trminos sintcticos) para producir valores
(entidades abstractas que son vistas como respuestas). Todo valor tiene asociado un tipo.
(Intuitivamente, podemos pensar que los tipos son conjuntos de valores.) Ejemplos de
expresiones son los valores atmicos tales como el entero 5, o el carcter 'a', o la funcin
\x -> x+1, y los valores estructurados como la lista [1,2,3] y el par ('b',4).
Ya que las expresiones denotan valores, las expresiones de tipo son trminos sintcticos
que denotan tipos. Ejemplos de expresiones de tipo son los tipos atmicos Integer
(enteros con precisin ilimitada), Char (caracteres), Integer->Integer (funciones que
aplican Integer sobre Integer), as como los tipos estructurados [Integer] (lista
homognea de enteros) y (Char,Integer) (par formado por un carcter y un entero).
Todos los valores de Haskell son de primera categora ("first-class") ---pueden ser
argumentos o resultados de funciones, o pueden ser ubicados en estructuras de datos, etc.
Por otro lado, los tipos de Haskell no son de primera categora. En cierto sentido, los tipos
describen valores, y la asociacin de un valor con su tipo se llama un tipificado (typing).
Usando los ejemplos anteriores, podemos escribir "tipificaciones" como los siguientes:
5
'a'
inc
[1,2,3]
('b',4)

::
::
::
::
::

Integer
Char
Integer -> Integer
[Integer]
(Char,Integer)

El smbolo "::" puede leerse "tiene el tipo".


En Haskell las funciones se definen usualmente a travs de una coleccin de ecuaciones.
Por ejemplo, la funcin inc puede definirse por una nica ecuacin:
inc n

= n+1

Una ecuacin es un ejemplo de declaracin. Otra forma de declaracin es la declaracin de


tipo de una funcin o type signature declaration (4.4.1), con la cual podemos dar de forma
explcita el tipo de una funcin; por ejemplo, el tipo de la funcin inc:
inc

:: Integer -> Integer

Veremos ms detalles sobre definiciones de funciones en la Seccin 3.


Por razones pedaggicas, cuando queramos indicar que una expresin e 1 se evala, o
"reduce" a otra expresin o valor e2, escribiremos:

e1 => e2
Por ejemplo:
inc (inc 3)

=> 5

El sistema de tipificacin esttico de Haskell define formalmente la relacin entre tipos y


valores (4.1.4). Esta tipificacin esttica asegura que un programa Haskell est bien
tipificado (type safe); es decir, que el programador no puede evaluar expresiones con tipos
errneos. Por ejemplo, no podemos sumar dos caracteres, ya que la expresin 'a'+'b' est
mal tipificada. La ventaja principal del tipificacin esttica es bien conocida: todos los
errores de tipificado son detectados durante la compilacin. No todos los errores son
debidos al sistema de tipos; una expresin tal como 1/0 es tipificable pero su evaluacin
provoca un error en tiempo de ejecucin. No obstante, el sistema de tipos puede encontrar
errores durante la compilacin, lo que proporciona al programador una ayuda para razonar
sobre los programas, y tambin permite al compilador generar un cdigo ms eficiente (por
ejemplo, no se requiere ninguna informacin de tipo o pruebas durante la ejecucin).
El sistema de tipos tambin asegura que los tipos que el usuario proporciona para las
funciones son correctos. De hecho, el sistema de tipos de Haskell es lo suficientemente
potente como para describir cualquier tipo de funcin (con algunas excepciones que
veremos ms tarde) en cuyos caso diremos que el sistema de tipos infiere tipos correctos.
No obstante, son aconsejables las oportunas declaraciones de tipos para las funciones, como
la proporcionada para la funcin inc, ya que el tipificado de funciones es una forma
eficiente de documentar y ayudar al programador a detectar errores.
[El lector habr notado que los identificadores que comienzan con mayscula denotan tipos
especficos, tales como Integer y Char, pero no los identificadores que denotan valores,
como inc. Esto no es un convenio: es obligatorio debido a la sintaxis de Haskell. Adems,
todos los caracteres, maysculas y minsculas, son significativos: foo, fOo, y fOO son
identificadores distintos.]

2.1.

Tipos Polimrficos

Haskell proporciona tipos polimficos ---tipos que son cuantificados universalmente sobre
todos los tipos. Tales tipos describen esencialmente familias de tipos. Por ejemplo,
(para_todo a)[a] es la familia de las listas de tipo base a, para cualquier tipo a. Las listas
de enteros (e.g. [1,2,3]), de caracteres (['a','b','c']), e incluso las listas de listas de
interos, etc., son miembros de esta familia. (Ntese que [2,'b'] no es un ejemplo vlido,
puesto que no existe un tipo que contenga tanto a 2 como a 'b'.)
[Los identificadores tales como el anterior a se llaman variables de tipo, y se escriben en
minscula para distinguirlas de tipos especficos, como Integer. Adems, ya que Haskell

solo permite el cuantificador universal, no es necesario escribir el smbolo correspondiente


a la cuantificacin universal, y simplemente escribimos [a] como en el ejemplo anterior.
En otras palabras, todas las variables de tipos son cuantificadas universalmente de forma
implcita.]
Las listas constituyen una estructura de datos comunmente utilizada en lenguajes
funcionales, y constituyen una buena herramienta para mostrar los principios del
polimorfismo. En Haskell, la lista [1,2,3] es realmente una abreviatura de la lista
1:(2:(3:[])), donde [] denota la lista vaca y : es el operador infijo que aade su primer
argumento en la cabeza del segundo argumento (una lista). ( : y [] son, respectivamente,
los operadores cons y nil del lenguaje Lisp) Ya que : es asociativo a la derecha, tambin
podemos escribir simplemente 1:2:3:[].
Como ejemplo de funcin definida por el usuario y que opera sobre listas, consideremos el
problema de contar el nmero de elementos de una lista:
length
length []
length (x:xs)

:: [a] -> Integer


= 0
= 1 + length xs

Esta definicin es auto-explicativa. Podemos leer las ecuaciones como sigue: "La longitud
de la lista vaca es 0, y la longitud de una lista cuyo primer elemento es x y su resto es xs
viene dada por 1 ms la longitud de xs." (Ntese el convenio en el nombrado: xs es el
plural de x, y x:xs debe leerse: "una x seguida de varias x).
Este ejemplo, adems de intuitivo, enfatiza un aspecto importante de Haskell que debemos
aclarar: la comparacin de patrones (pattern matching). Los miembros izquierdos de las
ecuaciones contienen patrones tales como [] y x:xs. En una aplicacin o llamada a la
funcin, estos patrones son comparados con los argumentos de la llamada de forma
intuitiva ([] solo "concuerda" (matches) o puede emparejarse con la lista vacia, y x:xs se
podr emparejar con una lista de al menos un elemento, instancindose x a este primer
elemento y xs al resto de la lista). Si la comparacin tiene xito, el miembro izquierdo es
evaluado y devuelto como resultado de la aplicacin. Si falla, se intenta la siguiente
ecuacin, y si todas fallan, el resultado es un error.
La definicin de funciones a travs de comparacin de patrones es usual en Haskell, y el
usuario deber familiarizarse con los distintos tipos de patrones que se permiten;
volveremos a esta cuestin en la Seccin 4.
La funcin length es tambin un ejemplo de funcin polimrfica. Puede aplicarse a listas
con elementos de cualquier tipo, por ejemplo [Integer], [Char], o [[Integer]].
=> 3
length ['a','b','c'] => 3
length [[1],[2],[3]] => 3
length [1,2,3]

He aqu dos funciones polimrficas muy tiles sobre listas, que usaremos ms tarde. La
funcin head devuelve el primer elemento de una lista, y la funcin tail devuelve la lista
salvo el primero:
head
head (x:xs)

:: [a] -> a
= x

tail
tail (x:xs)

:: [a] -> [a]


= xs

Al contrario que length, estas funciones no estan definidas para todos los posibles valores
de su argumento. Cuando las funciones son aplicadas a la lista vaca se produce un error en
tiempo de ejecucin.
Vemos que algunos tipos polimrficos son ms generales que otros en el sentido de que el
conjunto de valores que definen es ms grande. Por ejemplo, el tipo [a] es ms general
que [Char]. En otras palabras: el tipo [Char] puede ser derivado del tipo [a] a travs de
una sustitucin adecuada de a. Con respecto a este orden generalizado, el sistema de tipos
de Haskell tiene dos propiedades importantes: en primer lugar, se garantiza que toda
expresin bien tipificada tenga un nico tipo principal (descrito despus), y en segundo
lugar, el tipo principal puede ser inferido automticamente (4.1.4). En comparacin con un
lenguaje con tipos monomrficos como C, el lector encontrar que el polimrfismo
enriquece la expresividad, y que la inferencia de tipos reduce la cantidad de tipos usados
por el programador.
El tipo principal de una expresin o funcin es el tipo ms general que, intuitivamente,
"contiene todos los ejemplares de la expresin." Por ejemplo, el tipo principal de head es
[a]->a; los tipos [b]->a, a->a, o el propio a son demasiado generales, mientras que algo
como [Integer]->Integer es demasiado concreto. La existencia de un nico tipo
principal es la caracterstica esencial del sistema de tipos de Hindley-Milner, que es la base
del sistema de tipos de Haskell, ML, Miranda, ("Miranda" es marca registrada de Research
Software, Ltd.) y otros lenguajes (principalmente funcionales) .

2.2.

Tipos definidos por el usuario

Podemos definir nuestros propios tipos en Haskell a travs de una declaracin data, que
introduciremos con una serie de ejemplos (4.2.1).
Un dato predefinido importante en Haskell corresponde a los valores de verdad:
data Bool

= False | True

El tipo definido con tal declaracin es Bool, y tiene exactamente dos valores: True y
False. Bool es un ejemplo de constructor de tipo (sin argumentos), mientras que True y
False son constructores de datos (o constructores, para abreviar).

En forma similar, podemos definir un tipo color:


data Color

= Red | Green | Blue | Indigo | Violet

Tanto Bool como Color son ejemplos de tipos enumerados, puesto que constan de un
nmero finito de constructores.
El siguiente es un ejemplo de tipo con un solo constructor de dato:
data Point a

= Pt a a

Al tener un solo constructor, un tipo como Point es llamado a menudo un tipo tupla, ya
que esencialmente es un producto cartesiano (en este caso binario) de otros tipos. (La tuplas
son conocidas en otros lenguajes como registros.) Por el contrario, un tipo multiconstructor, tal como Bool o Color, se llama una "suma de tipos" o tipo unin (disjunta).
Sin embargo, lo ms importante es que Point es un ejemplo de tipo polimrfico: para
cualquier tipo t, define el tipo de los puntos cartesianos que usan t como eje de
coordenadas. El tipo Point puede tambin verse como un constructor de tipos unario, ya
que a partir de un tipo t podemos obtener un nuevo tipo Point t. (En el mismo sentido,
usando el ejemplo de la listas, [] es tambin un constructor de tipos: podemos aplicar el
constructor [] a un tipo t para obtener un nuevo tipo [t]. La sintaxis de Haskell permite
escribir [t] en lugar de [] t. Similarmente, -> es otro constructor de tipos binario: dados
dos tipos "t" y "u", t->u es el tipo de las funciones que aplican datos de tipo "t" a elementos
de tipo "u".)
Ntese que el tipo del constructor de datos Pt es a -> a -> Point a, y las siguientes
asignaciones de tipos son vlidas:
Pt 2.0 3.0
Pt 'a' 'b'
Pt True False

:: Point Float
:: Point Char
:: Point Bool

Por otro lado, una expresin tal como Pt 'a' 1 est errneamente tipificada, ya que 'a' y
1 son de tipos diferentes.
Es importante distinguir entre la aplicacin de un constructor de datos para obtener un
valor, y la aplicacin de un constructor de tipos para obtener un tipo; el primero tiene lugar
durante el tiempo de ejecucin, que es cuando se computan cosas en Haskell, mientras que
el ltimo tiene lugar en tiempo de compilacin y forma parte del proceso de tipificado que
asegura un "tipo seguro".
[Constructores de tipo como Point y constructores de datos como Pt aparecen en niveles
distintos de la declaracin, lo que permite que el mismo nombre pueda usarse como
constructor de tipos y como constructor de datos, como vemos en:
data Point a = Point a a

Esto puede llevar a una pequea confusin al principio, pero sirve para crear un enlace
obvio entre el constructor de datos y el de tipo.]

2.2.1.

Tipos recursivos

Los tipos pueden ser recursivos, como el siguiente tipo para rboles binarios:
data Tree a

= Leaf a | Branch (Tree a) (Tree a)

Con ello hemos definido un tipo polimrfico cuyos elementos son o bien hojas conteniendo
un valor de tipo a, o nodos internos ("ramas") conteniendo (en forma recursiva) dos
subrboles.
En la lectura de declaraciones de datos como la anterior, recordemos que Tree es un
constructor de tipos, mientras que Branch y Leaf son constructores de datos. La
declaracin anterior, adems de establecer una conexin entre estos constructores, define
esencialmente los tipos para los constructores Branch y Leaf:
Branch
Leaf

:: Tree a -> Tree a -> Tree a


:: a -> Tree a

Con este ejemplo tenemos un tipo suficientemente rico que permite definir algunas
funciones (recursivas) interesantes que hagan uso de ste. Por ejemplo, supongamos que
queremos definir una funcin fringe que devuelva todos los elementos de las hojas de un
rbol de izquierda a derecha. En primer lugar es esencial escribir el tipo de la nueva
funcin; en este caso vemos que el tipo debe ser Tree a -> [a]. Es decir, fringe es una
funcin polimrfica que, para cualquier tipo a, aplica rboles de a sobre listas de a. Una
definicin adecuada es la siguiente:
fringe
:: Tree a -> [a]
fringe (Leaf x)
= [x]
fringe (Branch left right) = fringe left ++ fringe right

donde ++ es el operador infijo que concatena dos listas (su definicin completa se ver en la
Section 9.1). Al igual que la funcin length vista anteriormente, la funcin fringe est
definida mediante comparacin de patrones, salvo que los patrones implicados son los
constructores de la definicin dada por el usuario: Leaf y Branch. [Ntese que los
parmetros formales son fcilmente identificados ya que comienzan con letras minsculas.]

2.3.

Sinnimos de Tipos

Por conveniencia, Haskell proporciona una forma para definir sinnimos de tipos; es decir,
nombres de tipos usados varias veces. Los sinnimos de tipo son creados a travs de una
declaracin type (4.2.2). He aqu algunos ejemplos:
type
type
type
data

String
Person
Name
Address

=
=
=
=

[Char]
(Name,Address)
String
None | Addr String

Los sinnimos no definen tipos nuevos, sino simplemente proporcionan nuevos nombres a
tipos ya existentes. Por ejemplo, el tipo Person -> Name es precisamente equivalente al
tipo (String,Address) -> String. Los nombres nuevos son a menudo ms cortos que
los tipos nombrados, pero ste no es el nico propsito de los sinnimos de tipos: stos
pueden mejorar la legibilidad de los programas a travs de nemotcnicos; en efecto, los
ejemplos anteriores enfatizan este hecho. Podemos dar nuevos nombres a tipos
polimrficos:
type AssocList a b

= [(a,b)]

Este es el tipo de las "listas de asociaciones" que asocian valores de tipo a con otros de tipo
b.

2.4.

Los tipos predefinidos no son especiales

Antes hemos introducido varios tipos "predefinidos" tales como listas, tuplas, enteros y
caracteres. Tambin mostramos como el programador puede definir nuevos tipos. Adems
de una sintaxis especial los tipos predefinidos tienen algo ms de especial? La respuesta es
no. La sintaxis especial es por conveniencia y consistencia, junto a algunas razones
histricas, pero no tiene ninguna consecuencia semntica.
Enfatizamos este punto diciendo que la apariencia de las declaraciones de stos tipos
predefinidos es especial. Por ejemplo, el tipo Char puede ser descrito en la forma:
data Char
Haskell

= 'a' | 'b' | 'c' | ...

-- Esto no es cdigo

| 'A' | 'B' | 'C' | ...


| '1' | '2' | '3' | ...
...

-- vlido!

Los nombres de los constructores no son vlidos sintcticamente; ello lo podramos arreglar
escribiendo algo como lo siguiente:
data Char

= Ca | Cb | Cc | ...
| CA | CB | CC | ...
| C1 | C2 | C3 | ...
...

Tales constructores son ms concisos, pero no son los habituales para representar
caracteres.
En cualquier caso, la escritura de cdigo "pseudo-Haskell" tal como la anterior ayuda a
aclarar la sintaxis especial. Vemos que Char es, en efecto, un tipo enumerado compuesto de
un gran nmero de constructores (constantes). Por ejemplo, visto Char de esta forma
aclaramos qu patrones pueden aparecer en las definiciones de funciones; es decir, qu
constructores de este tipo podemos encontrarnos.
Este ejemplo tambin muestra el uso de los comentarios en Haskell; los caracteres -- y los
sucesivos hasta el final de la lnea son ignorados. Haskell tambin permite comentarios
anidados que tienen las forma {-...-} y pueden aparecer en cualquier lugar (2.2).]
Similarmente, podemos definir Int (enteros de precisin limitada) y Integer en la forma:
data Int
= -65532 | ... | -1 | 0 | 1 | ... | 65532
cdigo
data Integer =
... -2 | -1 | 0 | 1 | 2 ...

-- ms pseudo-

donde -65532 y 65532, representan el mayor y el menor entero en precisin fija para una
implementacin concreta. Int es un tipo enumerado ms largo que Char, pero es finito! Por
el contrario, el pseudo-cdigo para Integer (el tipo de los enteros con precisin arbitraria)
debe verse como un tipo enumerado infinito.
Las tuplas tambin son fciles de definir en la misma forma:
data (a,b)
cdigo
data (a,b,c)
data (a,b,c,d)
.
.
.

= (a,b)

-- ms peudo-

= (a,b,c)
= (a,b,c,d)
.
.
.

Cada una de las declaraciones anteriores define una tupla de una longitud particular, donde
(...) juega distintos papeles: a la izquierda como constructor de tipo, y a la derecha como
constructor de dato. Los puntos verticales despus de la ltima declaracin indican un
nmero infinito de tales declaraciones, reflejando el hecho de que en Haskell estn
permitidas las tuplas de cualquier longitud.
La listas son manipulables fcilmente, y lo que es ms importante, son recursivas:
data [a]
cdigo

= [] | a : [a]

-- ms peudo-

Vemos que esto se ajusta a lo ya dicho sobre listas: [] es la lista vaca, y : es el constructor
infijo de listas; de esta forma [1,2,3] es equivalente a la lista 1:2:3:[]. (: es asociativo a
la derecha.) El tipo de [] es [a], y el tipo de : es a->[a]->[a].

[De esta forma ":" est definido con una sintaxis legal---los constructores infijos se
permiten en declaraciones data, y (para describir la comparacin de patrones) son
distinguidos de los operadores infijos ya que comienzan con el carcter ":" (una propiedad
satisfecha trivialmente por ":").]
En este punto, el lector deber notar con cuidado las diferencias entre tuplas y listas, ya que
las definiciones anteriores lo aclaran suficientemente. En particular, ntese la naturaleza
recursiva de las listas, con longitud arbitraria y cuyos elementos son homogneos, y la
naturaleza no recursiva de una tupla concreta, que tiene una longitud fija, en la cual los
elementos son heterogneos. Las reglas de tipificado para tuplas y listas deberan quedar
claras ahora:
Para (e1,e2,...,en), n>=2, si ti es el tipo de ei, entonces el tipo de la tupla es (t1,t2,...,tn).
Para [e1,e2,...,en], n>=0, cada ei debe tener el mismo tipo t, y el tipo de la lista es [t].

2.4.1

Listas por comprensin y Secuencias Aritmticas

Como en algunos dialectos de Lisp, las listas son muy tiles en Haskell, y al igual que en
otros lenguajes funcionales, existe an una sintaxis ms adecuada para su descripcin.
Adems de los constructores de listas ya introducidos, Haskell proporciona expresiones
conocidas como listas por comprensin que introducimos con un ejemplo:
[ f x | x <- xs ]

Intuitivamente, esta expresin puede leerse como "la lista de todos los f x tales que x
recorre xs." La similitud con la notacin de los conjuntos no es una coincidencia. La frase
x <- xs se llama un generador, y pueden utilizarse varios, como en :
[ (x,y) | x <- xs, y <- ys ]

Tal lista por comprensin determina el producto cartesiano de dos listas xs y ys. Los
elementos son seleccionados como si los generadores fueran anidados de izquierda a
derecha (con el de ms a la derecha variando el ltimo); es decir, si xs es [1,2] e ys es
[3,4], el resultado es [(1,3),(1,4),(2,3),(2,4)].
Adems de los generadores, se permiten expresiones booleanas llamadas guardas que
establecen restricciones sobre los elementos generados. Por ejemplo, he aqu una definicin
compacta del algoritmo de ordenacin favorito de todo el mundo:
quicksort []
quicksort (x:xs)

=
=
++
++

[]
quicksort [y | y <- xs, y<x ]
[x]
quicksort [y | y <- xs, y>=x]

Como otra ayuda en la descripcin de listas, Haskell admite una sintaxis especial para
secuencias aritmticas, que mostramos con una serie de ejemplos:
=> [1,2,3,4,5,6,7,8,9,10]
[1,3..10] => [1,3,5,7,9]
[1,3..]
=> [1,3,5,7,9, ... (secuencia infinita)
2.4.2 Cadenas
[1..10]

Como otro ejemplo de sintaxis especial para tipos predefinidos, hacemos notar que la
cadena de caracteres "hello" es una forma simplificada de la lista de caracteress
['h','e','l','l','o']. Adems, el tipo de "hello" es String, donde String es un
sinnimo de tipo predefinido:
type String

= [Char]

Esto significa que podemos usar las funciones polimrficas sobre listas para operar con
cadenas (strings). Por ejemplo:
"hello" ++ " world"

=> "hello world"

2.2. Funciones

2.3. Intervalos

2.4. Operadores

2.5. Aplicaciones de las listas


Pairs, Triples and More
In addition to single values, we should also address multiple values. For instance,
we may want to refer to a position by its x/y coordinate, which would be a pair of
integers. To make a pair of integers is simple: you enclose the pair in parenthesis
and separate them with a comma. Try the following:

Here, we have a pair of integers, 5 and 3. In Haskell, the first element of a pairneed
not have the same type as the second element: that is, pairs are allowed to be
heterogeneous heterogeneous. For instance, you can have a pair of an integer with
a string. This contrasts with lists, which must be made up of elements of all the same
type (we will discuss lists further in Section 3.3).
There are two predefined functions that allow you to extract the first and
secondvelements of a pair. They are, respectively, fst and snd. You can see how
they workvbelow:

In addition to pairs, you can define triples, quadruples etc. To define a triple and a
quadruple, respectively, we write:

Exercise 3.2 Use a combination of fst and snd to extract the character out of the
tuple ((1,a),"foo").

Lists
The primary limitation of tuples is that they hold only a fixed number of elements:
pairs hold two, triples hold three, and so on. A data structure that can hold an
arbitrary number of elements is a list. Lists are assembled in a very similar fashion
to tuples, except that they use square brackets instead of parentheses. We can
define a list like:

Lists dont need to have any elements. The empty list is simply []. Unlike tuples, we
can very easily add an element on to the beginning of the list using the colon
operator. The colon is called the cons operator; the process of adding an element
is called consing. The etymology of this is that we are constructing a new list from
an element and an old list. We can see the cons operator in action in the following
examples:

We can actually build any list by using the cons operator (the colon) and the empty
list:

In fact, the [5,1,2,3,4] syntax is syntactic sugar for the expression using the explicit
cons operators and empty list. If we write something using the [5,1,2,3,4] notation,
the compiler simply translates it to the expression using (:) and [ ].

One further difference between lists and tuples is that, while tuples are
heterogeneous, lists must be homogenous. This means that you cannot have a list
that holds both integers and strings. If you try to, a type error will be reported. Of
course, lists dont have to just contain integers or strings; they can also contain tuples
or even other lists. Tuples, similarly, can contain lists and other tuples. Try some of
the following:

There are two basic list functions: head and tail. The head function returns the first
element of a (non-empty) list, and the tail function returns all but the first element of
a (non-empty) list. To get the length of a list, you use the length function:

2.6. rboles

UNIDAD 3. Evaluacin perezosa


RED CONCEPTUAL

La estrategia de evaluacin perezosa


Evaluacin perezosa
Tcnicas de programacin funcional
perezosa

Competencia General de la Unidad:


Conocer la evaluacin perezosa.
Identificar la evaluacin perezosa como una de las funciones de la
programacin representativa.
Aplicar la evaluacin perezosa en la resolucin de problemas.
Disear programacin con modularidad.

Actividades de Aprendizaje
Identificar los conceptos bsicos de la evaluacin perezosa.
Describir las tcnicas de la programacin funcional perezosa.
Investigar, al menos, una tcnica de programacin funcional perezosa vista en
clase.
Realizar mapa conceptual de la evaluacin perezosa
Aplicar una tcnica de la programacin funcional perezosa, para resolver un
problema real a travs de la modularidad en una situacin sencilla.

3.1. Estrategias de evaluacin perezosa

3.2. Tcnicas de programacin funcional perezosa.


La semntica adoptada para el no determinismo es la eleccin en la invocacin (call-time
choice), por resultar mas natural para la programacin y mas eficaz en la ejecucin al
corresponderse con el mecanismo de comparticin.
En el no-determinismo existen varias tcnicas como son:

Tcnica de Backtracking (prolog): si una alternativa falla, el flujo retorna hasta la


ltima decisin e intenta otra.
Tecnica de guardias (guards): si mas de una es cierta, se escoge cualquiera de ellas.
Tecnica de aprendizaje reforzado (A-LISP): Recordar decisiones exitosas y
aumentar su prioridad asi como considerar las decisiones en el contexto del estado
mutable.

BUSQUEDA NO DETERMINISTA
Un algoritmo no determinista
-Ofrece muchos posibles resultados
-Emplean modelos de computacin tales como la maquina de turing probabilstica, que no
son deterministas
-puede simularse utilizando la lista de xitos como por ejemplo x=x, x candidatos, validos
DATOS NO DETERMINISTAS
Requiere tipo de datos diferente como son
Data list m a= nil (cons (m a)(m(list a))
Puede representar lista perezosa no determinista.
Cons [2] [Nil, cons[1]]:: list{} int
Los argumentos de cons representan computacin no determinista, permute y lsSorted se
pueden adaptar a la lista de tipo permute y genera permutaciones perezosamente los
rendimientos isSorted [true, false]es aplicada por encima de la lista (s).
PROGRAMACION FUNCIONAL-LOGICA
La programacin lgica, junto con la funcional, forma parte de los que se conoce como
programacin declarativa. En los lenguajes tradicionales, la programacin consiste en como

resolver un problema mediante sentencias; en la programacin lgica, se trabaja de forma


descriptiva, estableciendo relaciones entre entidades, indicando no como, sino que hacer.
La programacin funcional esta constituida mediante definicin de funciones puramente
matemticas. Esta basado en un modelo matemtico; lambda-calculo.
VENTAJAS Y DESVENTAJAS DE LOS LENGUAJES FUNCIONALES.
-Ventajas: mas faciles de escribir, depurar y mantener que los lenguajes imperativos gracias
a la ausencia de efectos de borde.
-Desventajas: se quedan cortos en portabilidad, riqueza de librerias interfaces con otros
lenguajes y herramientas de depuracion.

RESUMEN
Las diversas tcnicas estudiadas en la unidad nos presentan las tcnicas sobre
programacin de funciones, y sobre su evaluacin.
Mientras se consideren estas recomendaciones se prev la obtencin de un buen
software que cumple su objetivo de forma correcta.

UNIDAD 4. Fundamentos de la programacin lgica


RED CONCEPTUAL

Repaso de la lgica de primer orden

Unificacin y resolucin

Clusulas de Horn. Resolucin SLD.


Programacin lgica con clusulas
de Horn
Semntica de los programas lgicos
Fundamentos de la
programacin lgica

Representacin clausada del conocimiento

Consulta de una base de clusulas

Espacios de bsqueda
Programacin lgica con nmeros,
listas y rboles
Control de bsqueda en programas
lgicos
Manipulacin de trminos. Predicados
metalgicos

Competencia General de la Unidad:

Conocer las ventajas y desventajas del paradigma de programacin lgica.


Identificar los elementos de la programacin lgica.
Aplicar la programacin lgica en la resolucin de problemas reales.
Disear sistemas expertos con programacin lgica.

Actividades de Aprendizaje

Identificar los conceptos bsicos de la programacin lgica.


Describir las clausulas de Horn y resolucin SLD, para identificar reglas de
inferencia lgica y emplearlas en la representacin del conocimiento.
Reconocer los elementos de la semntica de la programacin lgica para
interpretar el conocimiento y aplicarlo en su representacin.
Investigar, al menos, un lenguaje de programacin lgica diferente al
establecido para la materia.
Aplicar la programacin lgica para resolver un problema real, diseando
un sistema experto basado en el control de bsqueda lgica.

4.1. Repaso de lgica de primer orden

4.2. Unificacin y Resolucin


La Deduccin Natural consiste en un sistema de reglas de inferencia, es
decir, a partir de "algo" podemos deducir o "llegar a" "otra cosa", hasta que
encontramos una conclusin
METODO DE RESOLUCION
El Mtodo de Resolucin, es un intento de mecanizar el proceso de
deduccin natura. Las demostraciones se consiguen utilizando el mtodo
refutativo (reduccin al absurdo), es decir lo que intentamos es encontrar
contradicciones.
El mtodo de resolucin es una regla de inferencia que toma dos clausulas
y produce una tercera que es consecuencia lgica de estas. El proceso
consiste en identificar y borrar parejas complementarias de dos clausulas,
una de cada clausula y luego, combinar las otras literales para formar una
clausula nueva.
METODO DE UNIFICACION
La Unificacin es un procedimiento de emparejamiento que compara dos
literales y descubre si existe un conjunto de sustituciones que los haga
idnticos.
La idea bsica de la unificacin es muy sencilla.
En primer lugar se comprueba si los predicados coinciden. Si es as,
seguimos adelante; si no es que no son unificables.
Si el predicado concuerda, comenzamos a comparar los argumentos. Si el
primero de ellos coincide en ambos literales, continuamos con el
siguiente... y as hasta completar todos los argumentos.

4.3. Clusulas de Horn. Resolucin SLD

4.4. Programacin lgica con clusulas de Horn

Horn Clauses and Prolog


Proof by resolution involved finding the conjunctive normal form, which comprised
conjoined clauses, each of which was a disjunction of literals - ie,
L1

L2

L3...

A slightly form of this is a Horn Clause, where the restriction is that only one of the literals
is un-negated. For example:
1.
L1
2.
L1
3. M
4.
L1

L2
L2

L3 ...
L3 ...

are all Horn Clauses. It is straightforward to show that, for example, (2) is equivalent to
L1 L2 L3 ...=> M
or in goal-directed form:
M => L1 L2 L3 ...
This is the typical form of a statement in the logic programming language Prolog. There are
two modes in Prolog. In the consult mode, one supplies the system with axioms. (Note that
the ``'' is replaced by ``:-'', that capitalized symbols are variables, and that the ``.'' is
important.)
grandson(X,Y) :- son(X,Z),parent(Y,Z).
son(charles,elizabeth).
parent(george,elizabeth).

In query mode we might ask


?- grandson(elizabeth,charles).
no

with Prolog telling us that there are no database facts to verify the statement. Or we might
ask
?- grandson(W,george).

Starting with this query, Prolog tries to justify each literal on the RHS by finding a
matching literal in the LHS of another clause in the database. In our example, it would find
dbase statement 1 and perform the unification (W/X, george/Y). So the RHS becomes
son(X,Z),parent(george,Z). It then uses dbase statement 2 to perform the unification
(X/charles, Z/elizabeth), leaving parent(george,elizabeth) to be verified. Obviously, dbase

statement 3 does this with no unification. The system returns the unification for W which is
(W/X/charles), ie charles.
?- grandson(W,george).
W = charles ?
yes

4.5. Consulta de una base de clusulas

4.6. Representacin causada del conocimiento.

4.7. Consulta de una base de clusulas


4.8. Espacios de bsqueda

4.9. Programacin lgica con nmeros, listas y rboles.

Hemos visto ya un buen nmero de convenciones que debemos utilizar para escribir
programas en Prolog. La ltima parte de este tema la dedicaremos a conocer
detalladamente las reglas sintcticas que hemos de seguir para que nuestras bases de
conocimientos sean reconocidas por Visual Prolog.
Como ya hemos estudiado, un programa Prolog no es ms que la especificacin de una
base de conocimientos lgica con las caractersticas siguientes:

Consta de una secuencia de oraciones, todas ellas


verdaderas, que expresan un conjunto de realidades sobre
los objetos del mundo representado, as como sobre sus
relaciones. Todas las variables tienen cuantificacin
universal implcita y cuando las variables aparecen en
oraciones distintas se consideran tambin distintas.
Se aceptan nicamente oraciones en forma de Clusula de
Horn, es decir, las oraciones son atmicas, o bien una
implicacin con un antecedente no negado y un
consecuente generalmente "expresiones" separados por
comas o por puntos y comas. Las comas significan
conjuncin y los puntos y comas significan disyuncin.
En vez de utilizar antecedentes negados en sus
implicaciones, en Prolog se emplea un operador de
negacin basado en el fallo: una meta no P se considera
demostrada si el sistema no logra demostrar P.

Aritmtica de VISUAL PROLOG


Las expresiones aritmticas en Visual Prolog se componen de operandos (nmeros y
variables), operadores (+, -, *, /, div, y mod) y parntesis: A = 1 + 6 / (11 + 3) * Z. Ver
Tabla 1.
Los nmeros "0x" o "0o" significan hexadecimal y octal respectivamente: 0xFFF = 4095;
86 = 0o112 + 12.
El valor de una expresin se puede calcular si todas las variables estn unificadas en el
momento de la evaluacin. El clculo ocurre entonces en un orden determinado por la
prioridad de los operadores aritmticos. Los operadores de mayor prioridad son evaluados
primero. Ver Tabla 2.
Operaciones
Operando 1

Operador

Operando 2

Resultado

+, -, *

entero

entero

real

+, -, *

entero

real

entero

+, -, *

real

real

real

+, -, *

real

real

entero real

entero real

real

entero

div

entero

entero

entero

mod

entero

entero

entero

Tabla 1

Orden de evaluacin
Si la expresin contiene subexpresiones entre parntesis, las subexpresiones se evalan
primero.
Si la expresin contiene multiplicacin o divisin, estas operaciones son realizadas
trabajando de izquierda a derecha a travs de la expresin.
Las operaciones de suma y resta son llevadas a cabo de izquierda a derecha tambin.
En el orden de evaluacin se tiene en cuenta, lgicamente, la precedencia de los
operadores.
Operador

Prioridad

+-

* / mod div

- + (unario

Tabla 2

Funciones y predicados
Visual Prolog posee una gran cantidad de funciones y predicados matemticos para realizar
las ms variadas operaciones. La lista completa se ofrece en la Tabla 3.
Nombre

Descripcin

X mod Y

Resto de X dividido entre Y.

X div Y

Cociente de X dividido entre Y.

abs(X)

Valor absoluto de X.

cos(X)

Coseno de X.

sin(X)

Seno de X.

tan(X)

Tangente de X.

arctan(X)

Arcotangente de X.

exp(X)

e elevado al valor almacenado en X. (Exponencial).

ln(X)

Logaritmo neperiano de X.

log(X)

Logaritmo en base 10 de X.

sqrt(X)

Raz cuadrada de X.

random(X)

Almacena en X un nmero aleatorio real entre 0 y 1.

random(X, Y)

Almacena en Y un nmero aleatorio en el intervalo 0 <= Y


< X.

round(X)

Valor redondeado de X. El resultado es un nmero real.

trunc(X)

Valor truncado de X. El resultado es un nmero real.

val(domain,X)

Conversin explcita entre dominios numricos.


Tabla 3

Comparaciones
En Visual Prolog podemos comparar expresiones aritmticas, caracteres, cadenas de
caracteres y smbolos.
Las comparaciones de este tipo se realizan a travs de operadores relacionales. Ver Tabla 4.
Smbolo

Relacin

<

menor que

<=

menor o igual que

igual que

>

mayor que

>=

mayor o igual que

<> o ><

distinto
Tabla 4

Comparacin de caracteres, cadenas de caracteres y smbolos


Adems de las expresiones numricas, podemos comparar caracteres, cadenas y smbolos:
'a' < 'b'; "antony" > "antonia" y P1 = peter, P2 = sally, P1 > P2.

Caracteres: Visual Prolog convierta la comparacin 'a' <


'b' a su expresin aritmtica correspondiente 97 < 98,
usando el cdigo ASCII correspondiente a cada carcter.
Cadenas de caracteres: Cuando se comparan dos cadenas o
smbolos, la comparacin se realiza carcter a carcter
en sus correspondientes posiciones. El resultado es el
mismo que se consigue comparando el carcter inicial a
menos que los dos sean iguales en cuyo caso se pasa al
siguiente. Cuando se encuentran dos caracteres iguales,
el proceso de comparacin termina y se produce el
resultado.
Smbolos: No pueden ser comparados directamente debido a
la sintaxis. Primero deben ser unificados a variables o
escritos como cadenas de caracteres.

RBOLES
Un rbol es una estructura con una definicin puramente recursiva, ya que se puede
considerar como el elemento raz cuyos hijos son, a su vez, rboles. Si el rbol tiene
nicamente dos hijos se denomina rbol binario. Este modelo especfico de rbol se utiliza
mucho para resolver gran cantidad de problemas en aspectos de programacin.
Un rbol se puede considerar, a su vez, un caso particular de grafo, donde todos los
caminos son acclicos.
La Figura 1 muestra un ejemplo de rbol.

Figura 1
Ejemplo de rbol

Muchos problemas de Inteligencia Artificial donde interviene el concepto de bsqueda se


resuelven mediante la implementacin de rboles. Los rboles de juego o los utilizados en
la resolucin de problemas relacionados con el procesamiento de lenguaje natural son casos
muy concretos y descriptivos. Por lo tanto, podemos notar que el manejo eficiente de estas
estructuras es sumamente importante para conseguir programas de calidad en este mbito
de la Ciencia.
Ya vimos que Prolog es un lenguaje que se adapta adecuadamente a este tipo de problemas.
De hecho la tcnica de resolucin que utiliza Prolog se basa en la construccin de un rbol
de bsqueda de soluciones, luego podemos concluir que el conocimiento de esta estructura
es clave para este tipo de metodologa declarativa.
Como en cualquier lenguaje, lo que necesitamos saber es la forma de declarar el rbol, ya
que su implementacin se puede realizar de muchas formas, por ejemplo, aunque una lista
es un caso particular de rbol, un rbol se puede representar a travs de listas, aunque en el
caso de Visual Prolog, estudiaremos la construccin de rboles utilizando objetos
compuestos recursivos.
Dado que un rbol est formado por la raz y un conjunto de hijos, podemos representarlo
utilizando la siguiente notacin:
oracin (sujeto (artculo (el), sustantivo (hombre)), predicado (verbo (come), CD (pan)))

El rbol generado se muestra en la Figura 2.

Figura 2
rbol de anlisis de una frase en espaol

Como se observa, el uso de un predicado con dos argumentos en el caso de rbol binario o
N argumentos en el caso de rbol N-ario es una forma sencilla de representar un rbol.
Mediante objetos compuestos recursivos del tipo arbol(nodo, hijoizq, hijoder), donde
hijoizq e hijoder son tambin rboles, podemos representar un rbol binario. El rbol vaco
se representa a travs del hecho vacio:
arbol(1,arbol(2,arbol(4,vacio,vacio),arbol(5,vacio,vacio)),arbol(3,vacio,vacio))
En la seccin DOMAINS podemos crear un tipo rbol de enteros del modo siguiente:
mi_arbol= arbol(INTEGER, mi_arbol, mi_arbol); vacio
Operaciones con rboles representados mediante objetos compuestos recursivos
domains
arbol= nodo(integer, arbol, arbol); vacio
lista= integer*

predicates
concatenar(lista, lista, lista)
preorden(arbol, lista)
inorden(arbol, lista)
postorden(arbol, lista)
clauses
concatenar([],[],[]):-!.
concatenar([],L2,L2):-!.
concatenar(L1,[],L1):-!.
concatenar([X|Y],L2,[X|Aux]):-concatenar(Y,L2,Aux).
preorden(vacio,[]):-!.
preorden(nodo(X,Izq,Der),[X|L]):-preorden(Izq,L1),
preorden(Der,L2),
concatenar(L1,L2,L).
inorden(vacio,[]):-!.
inorden(nodo(X,Izq,Der),L):-inorden(Izq,L1),
inorden(Der,L2),
concatenar(L1,[X|L2],L).
postorden(vacio,[]):-!.
postorden(nodo(X,Izq,Der),L):-postorden(Izq,L1),
postorden(Der,L2),
concatenar(L1,L2,L3),
concatenar(L3,[X],L).
goal
inorden(nodo(1,nodo(2,nodo(4,vacio,vacio),nodo(5,vacio,vacio)),nodo(3,vacio,vacio)), L1),
preorden(nodo(1,nodo(2,nodo(4,vacio,vacio),nodo(5,vacio,vacio)),nodo(3,vacio,vacio)), L2),
postorden(nodo(1,nodo(2,nodo(4,vacio,vacio),nodo(5,vacio,vacio)),nodo(3,vacio,vacio)), L3).

LISTAS

Una lista se puede considerar como un caso particular de rbol del modo que se muestra en
la Figura 3.

Figura 3
Lista implementada en forma de rbol

A su vez, una lista se puede considerar de forma recursiva. Es decir, siempre est formada
por un elemento seguido de otra lista (ver Figura 4). Cuando la lista tienen un slo
elemento podemos considerar que est formada por dicho elemento y la lista vaca. Esta
definicin es muy interesante, ya que su conocimiento nos permitir llevar a cabo todos las
operaciones que se pueden realizar sobre las listas con poco esfuerzo.

Figura 4
Definicin recursiva de una lista

Hemos de recordar que en Prolog no existen estructuras para realizar bucles luego todo los
algoritmos que representemos se definirn de forma recursiva. El hecho de que la
implementacin de la lista sea tambin recursiva facilita la construccin de operaciones
sobre la misma.
Es necesario comprender este tipo de estructura para construir algoritmos eficientes. La
mayor parte de las operaciones que se realizan sobre una lista implica un recorrido de la
misma, luego hemos de centrarnos en conocer cmo se lleva a cabo este algoritmo
utilizando tcnicas de recursividad.
Una lista se puede especificar en un predicado o en un objetivo a travs de:

una constante: [a, b, c, 1, pepe]


una variable: L
la estructura [Cabeza|Cola] que almacenar el primer
elemento en la variable Cabeza y el resto en la variable
Cola.

Las listas pueden ser homogneas o heterogneas, es decir, almacenar elementos del mismo
tipo, o elementos de distinto tipo.
Para definir un tipo de lista en particular es necesario declararla en la seccin DOMAINS.
lista= elementos* (lista de una dimensin)
lista2= elementos** (lista de dos dimensiones)
lista3= elementos*** (lista de tres dimensiones)...
Es interesante observar la sintaxis de definicin de una lista: elementos representa el
dominio o tipo de los elementos que componen la lista.
El tipo elementos puede representar un dominio simple, es decir, slo un tipo de elementos
se corresponde con dicho dominio o un dominio complejo, donde varios tipos de elementos
se corresponden con dicho dominio.
Por ejemplo, una lista homognea de elementos simples estara definida como:
lista= integer*
Una lista heterognea de elementos estara definida como:
listaenteros=integer*
elementos= i(integer); s(symbol); c(char); le(listaenteros)

lista= elementos*
Ejemplo:
domains
listaenteros= integer*
elementos= i(integer); c(char); s(symbol); le(listaenteros)
lista= elementos*
predicates
recorrer(lista)
clauses
recorrer([]):-!.
recorrer([X|Y]):-write(X), nl, recorrer(Y).
goal
recorrer([i(1),c('a'),s(pepe),i(5),c('b'),le([1,2,3])]).

Se observa que la lista puede contener cuatro tipo de elementos distintos: enteros,
caracteres, smbolos y listas de enteros. En la seccin de declaracin del dominio o tipo
elementos no podemos escribir:
elementos= integer; char; symbol; listaenteros

para expresar que dicho dominio agrupa a cuatro tipos de elementos distintos sino que la
sintaxis a utilizar es aquella que representa que elementos agrupa a cuatro tipos de objetos
compuestos distintos.
El resultado de la ejecucin de la meta es el siguiente:
i(1)
c('a')
s("pepe")
i(5)
c('b')
le([1,2,3])

yes

Las operaciones tpicas que se pueden realizar sobre listas son: la insercin de elementos al
principio, al final, en orden; borrado, bsqueda de elementos, recorrido, eliminacin de
duplicados y, en general, todas las de las que se pueden realizar sobre conjuntos de
elementos tales como: interseccin, unin, diferencia, pertenencia, comprobacin de lista
vaca, concatenacin, etc.
Las listas se pueden utilizar para implementar otras estructuras tales como listas circulares,
vectores, pilas, colas, rboles, grafos y matrices.
De cada estructura nos interesa saber cules son los algoritmos para acceder a ellas. Una
vez que conocemos, perfectamente, el tipo de operaciones que las definen, cualquier tipo de
implementacin es vlida. Por ejemplo, es frecuente usar una implementacin mediante
listas para plasmar matrices.
Por otro lado, es fundamental aplicar tcnicas de diseo descendente para resolver todos
nuestros problemas e implementar las estructuras necesarias en nuestras aplicaciones.

MATRICES
Podemos definir matrices a partir de listas, primero de 2 dimensiones y, ms tarde,
generalizar matrices de dimensin N.
En un lenguaje imperativo, recorrer una matriz de dos dimensiones implica el uso de un par
de bucles anidados, que proporcionan una complejidad computacional O(n2). Sin embargo,
en Prolog, no disponemos de este tipo de estructuras de control, por tanto, cualquier
operacin debe ser resuelta de forma recursiva mediante la declaracin formal de su
enunciado.
Un tratamiento elemento a elemento de las matrices tal y como se realiza en un lenguaje
imperativo no es adecuado en Prolog, por tanto, conviene entender la estructura matriz
como una lista de listas, y aplicar los algoritmos diseados sobre listas para resolver
problemas matriciales.
Una matriz de cuatro dimensiones se puede ver como la secuencia de un conjunto de
matrices de tres dimensiones, una matriz de tres dimensiones como un conjunto de matrices
de dos dimensiones, una matriz de dos dimensiones como un conjunto o lista de matrices
de una dimensin (vector o lista), por ltimo, un vector o lista no es ms que una secuencia
de elementos simples.

4.10. Control de bsqueda en programas lgicos

4.11. Manipulacion de Trminos.

BIBLIOGRAFIA
UNIDAD I
http://es.wikipedia.org/wiki/Estilo_de_programaci%C3%B3n
http://programacionlogicayfuncional.wordpress.com/2014/02/12/estilos-deprogramacion/
http://programacionlogicayfuncional.wordpress.com/2014/02/12/evaluacionde-expresiones/
http://programacionlogicayfuncional.wordpress.com/2014/02/13/definicionde-funciones/
http://users.dcc.uchile.cl/~lmateu/CC10A/Apuntes/deffun/index.html
UNIDAD II
http://sistemasumma.com/2011/09/04/tipos-de-datos-en-haskell/
Funciones http://www.cs.us.es/cursos/lp/practicas/tema-001.pdf
(Piensa en Haskell. JIMENEZ Jos A., Creative Commons. Sevilla 2012.)
(Yet Another Haskell Tutorial. Daume, Hal. 2006)
UNIDAD III
Evalacin perezosa. https://www.cs.us.es/~jalonso/cursos/pd09/temas/tema-10-1x2.pdf
Evaluacin perezosa. http://prezi.com/lhnyd5gqlj_-/unidad-3-evaliacionperezosa/

UNIDAD IV
Programacin Lgica.
http://clubensayos.com/Tecnolog%C3%ADa/ProgramacionLogica/1777196.html
Repaso de Lgica de Primer Orden. http://web.ing.puc.cl/~marenas/iic326010/clases/repaso-lpo.pdf
http://es.scribd.com/doc/71607751/Metodos-de-Resolucion-y-Unificacion
http://gpd.sip.ucm.es/jaime/docencia/pl/sld.pdf
http://wwwg.eng.cam.ac.uk/mmg/teaching/artificialintelligence/nonflash/resolution6.htm
http://gpd.sip.ucm.es/jaime/docencia/pl/busqueda.pdf