├── apuntes.pdf ├── apuntes ├── apuntes.pdf ├── machete.pdf ├── machete_II.pdf ├── imagenes │ ├── arbol_sld_prolog.png │ └── algoritmo_subtipado.png ├── machete_II.tex ├── page.layout.tex ├── secciones │ ├── programacion_logica.tex │ ├── objetos.tex │ ├── clasificacion.tex │ ├── introduccion.tex │ ├── logica_propocisional.tex │ ├── resolucion_sld.tex │ ├── subtipado.tex │ ├── prototipado.tex │ ├── logica_primer_orden.tex │ ├── inferencia_de_tipos.tex │ └── apendices.tex ├── apuntes.tex └── header.tex ├── practicas_enunciados ├── p2_lambda.pdf ├── p5_objetos.pdf ├── p7_logica.pdf ├── p1_funcional.pdf ├── p4_subtipado.pdf ├── p3_inferencia.pdf ├── p6_resolucion.pdf └── p0_pre_funcional.pdf ├── practicas_solucion ├── practica_0.pdf ├── practica_1.pdf ├── practica_2.pdf ├── practica_3.pdf ├── practica_4.pdf ├── practica_5.pdf ├── practica_6.pdf ├── practica_7.pdf ├── page.layout.tex ├── landscape.page.layout.tex ├── header.tex ├── practica_0.tex ├── practica_7.tex └── practica_5.tex ├── .gitignore ├── soluciones_haskell_js_prolog ├── index.html ├── Practica0.hs ├── practica7.pl ├── Practica1.hs └── practica5.js └── nota_util.txt /apuntes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/apuntes.pdf -------------------------------------------------------------------------------- /apuntes/apuntes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/apuntes/apuntes.pdf -------------------------------------------------------------------------------- /apuntes/machete.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/apuntes/machete.pdf -------------------------------------------------------------------------------- /apuntes/machete_II.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/apuntes/machete_II.pdf -------------------------------------------------------------------------------- /practicas_enunciados/p2_lambda.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_enunciados/p2_lambda.pdf -------------------------------------------------------------------------------- /practicas_enunciados/p5_objetos.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_enunciados/p5_objetos.pdf -------------------------------------------------------------------------------- /practicas_enunciados/p7_logica.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_enunciados/p7_logica.pdf -------------------------------------------------------------------------------- /practicas_solucion/practica_0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_solucion/practica_0.pdf -------------------------------------------------------------------------------- /practicas_solucion/practica_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_solucion/practica_1.pdf -------------------------------------------------------------------------------- /practicas_solucion/practica_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_solucion/practica_2.pdf -------------------------------------------------------------------------------- /practicas_solucion/practica_3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_solucion/practica_3.pdf -------------------------------------------------------------------------------- /practicas_solucion/practica_4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_solucion/practica_4.pdf -------------------------------------------------------------------------------- /practicas_solucion/practica_5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_solucion/practica_5.pdf -------------------------------------------------------------------------------- /practicas_solucion/practica_6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_solucion/practica_6.pdf -------------------------------------------------------------------------------- /practicas_solucion/practica_7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_solucion/practica_7.pdf -------------------------------------------------------------------------------- /apuntes/imagenes/arbol_sld_prolog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/apuntes/imagenes/arbol_sld_prolog.png -------------------------------------------------------------------------------- /practicas_enunciados/p1_funcional.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_enunciados/p1_funcional.pdf -------------------------------------------------------------------------------- /practicas_enunciados/p4_subtipado.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_enunciados/p4_subtipado.pdf -------------------------------------------------------------------------------- /apuntes/imagenes/algoritmo_subtipado.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/apuntes/imagenes/algoritmo_subtipado.png -------------------------------------------------------------------------------- /practicas_enunciados/p3_inferencia.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_enunciados/p3_inferencia.pdf -------------------------------------------------------------------------------- /practicas_enunciados/p6_resolucion.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_enunciados/p6_resolucion.pdf -------------------------------------------------------------------------------- /practicas_enunciados/p0_pre_funcional.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gianzamboni/plp-Verano/HEAD/practicas_enunciados/p0_pre_funcional.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | apuntes/_minted-apuntes 2 | resumen_plp/_minted-resumen 3 | resumen/_minted-* 4 | practicas_solucion/_minted-* 5 | resumen/_minted-resumen 6 | *.log 7 | *.aux 8 | *.out 9 | *.gz 10 | *.toc 11 | *.600pk -------------------------------------------------------------------------------- /soluciones_haskell_js_prolog/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Taller js 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /apuntes/machete_II.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,a4paper]{article} 2 | 3 | \input{header} 4 | 5 | \begin{document} 6 | \title{Resumen: Paradigmas de Lenguajes de Programación} 7 | 8 | \date{\today} 9 | 10 | \author{Zamboni, Gianfranco} 11 | 12 | 13 | \end{document} -------------------------------------------------------------------------------- /practicas_solucion/page.layout.tex: -------------------------------------------------------------------------------- 1 | \usepackage{fancyhdr} 2 | \pagestyle{fancy} 3 | 4 | %\renewcommand{\chaptermark}[1]{\markboth{#1}{}} 5 | \renewcommand{\sectionmark}[1]{\markright{\thesection\ - #1}} 6 | 7 | \fancyhf{} 8 | 9 | \fancyhead[LO]{\rightmark} % \thesection\ 10 | \fancyfoot[LO]{\small{PLP - Prácticas}} 11 | \fancyfoot[RO]{\thepage} 12 | \renewcommand{\headrulewidth}{0.5pt} 13 | \renewcommand{\footrulewidth}{0.5pt} 14 | \setlength{\hoffset}{-0.25in} 15 | \setlength{\textwidth}{16cm} 16 | %\setlength{\hoffset}{-1.1cm} 17 | %\setlength{\textwidth}{16cm} 18 | \setlength{\headsep}{0.5cm} 19 | \setlength{\textheight}{25cm} 20 | \setlength{\voffset}{-0.4in} 21 | \setlength{\headwidth}{\textwidth} 22 | \setlength{\headheight}{13.1pt} 23 | 24 | \renewcommand{\baselinestretch}{1.1} % line spacing -------------------------------------------------------------------------------- /practicas_solucion/landscape.page.layout.tex: -------------------------------------------------------------------------------- 1 | \usepackage{fancyhdr} 2 | \pagestyle{fancy} 3 | 4 | %\renewcommand{\chaptermark}[1]{\markboth{#1}{}} 5 | \renewcommand{\sectionmark}[1]{\markright{\thesection\ - #1}} 6 | 7 | \fancyhf{} 8 | 9 | \fancyhead[LO]{\rightmark} % \thesection\ 10 | \fancyfoot[LO]{\small{PLP - Prácticas}} 11 | \fancyfoot[RO]{\thepage} 12 | \renewcommand{\headrulewidth}{0.5pt} 13 | \renewcommand{\footrulewidth}{0.5pt} 14 | \setlength{\hoffset}{-0.25in} 15 | \setlength{\textwidth}{25cm} 16 | %\setlength{\hoffset}{-1.1cm} 17 | %\setlength{\textwidth}{16cm} 18 | \setlength{\headsep}{0.5cm} 19 | \setlength{\textheight}{15cm} 20 | \setlength{\voffset}{-0.4in} 21 | \setlength{\headwidth}{\textwidth} 22 | \setlength{\headheight}{13.1pt} 23 | 24 | \renewcommand{\baselinestretch}{1.1} % line spacing 25 | -------------------------------------------------------------------------------- /apuntes/page.layout.tex: -------------------------------------------------------------------------------- 1 | \usepackage{fancyhdr} 2 | \pagestyle{fancy} 3 | 4 | %\renewcommand{\chaptermark}[1]{\markboth{#1}{}} 5 | \renewcommand{\sectionmark}[1]{\markright{\thesection\ - #1}} 6 | 7 | \fancyhf{} 8 | 9 | \fancyhead[LO, LE]{Sección \rightmark} % \thesection\ 10 | \fancyfoot[LO, LE]{\small{Paradigmas de lenguajes de programación}} 11 | \fancyfoot[RO, RE]{\thepage} 12 | \renewcommand{\headrulewidth}{0.5pt} 13 | \renewcommand{\footrulewidth}{0.5pt} 14 | \setlength{\hoffset}{-0.25in} 15 | \setlength{\textwidth}{16cm} 16 | %\setlength{\hoffset}{-1.1cm} 17 | %\setlength{\textwidth}{16cm} 18 | \setlength{\headsep}{0.5cm} 19 | \setlength{\textheight}{25cm} 20 | \setlength{\voffset}{-0.4in} 21 | \setlength{\headwidth}{\textwidth} 22 | \setlength{\headheight}{13.1pt} 23 | 24 | \renewcommand{\baselinestretch}{1.1} % line spacing -------------------------------------------------------------------------------- /apuntes/secciones/programacion_logica.tex: -------------------------------------------------------------------------------- 1 | En este paradigma, las programas son un conjunto \textbf{hechos} y \textbf{reglas de inferencia} que sirven para inferir si un \textbf{objetivo} o \textbf{goal} es consecuencia de ellos. Es decir que, cuando escribimos un programa, \textbf{declaramos} expresiones que sabemos que son verdad (hechos y reglas) que nos permitirán probar, a través del uso de la lógica, que una expresión (objetivo) es verdad. 2 | 3 | En prolog, esta demostración, se hace a través de un motor de inferencia que se basa en el \textbf{método de resolución} para realizar la demostración. Vamos a ver métodos no deterministicos de resolución para expresiones de la lógica proposicional y de primer orden. Luego, agregaremos a estos métodos reglas que nos permitirán convertirlos en algoritmos determinísticos y las formas y condiciones que debe cumplir un programa para que sea compatible con estas reglas. 4 | -------------------------------------------------------------------------------- /nota_util.txt: -------------------------------------------------------------------------------- 1 | Por si sirve => 2 | 3 | //Objeto Singleton: 4 | var objeto_vacio={}; 5 | //no tiene prototype y por lo tanto sus instancias no tienen __proto__ 6 | objeto_vacio.estado = 1; 7 | console.log(objeto_vacio.estado); 8 | 9 | //Objeto creado a travez de una funcion 10 | function nroComplejo(r,i){ 11 | this.r = r; 12 | this.i = i; 13 | } 14 | //se puede crear un objeto c a partir de esa funcion con new 15 | var c = new nroComplejo(1,2); 16 | 17 | //los nros complejos, o sea, todos los objetos que se creen a partir de la funcion heredaran los metodos de instancia (r e i) y los de clase (los metodos definidos en el prototype) 18 | nroComplejo.prototype.estado = 0; 19 | console.log(c.estado); 20 | 21 | //cada instancia c tiene un atributo __proto__, que por default es el mismo que el prototype de todos los numeros complejos. 22 | c.__proto__.estado = 1; 23 | console.log(c.estado); 24 | 25 | //si cambiamos el campo estado del prototype, ya sea: c.__proto__ Ó nroComplejo.prototype, por default todas las instancias de numeros complejos veran esa modificación. lo comprobé acá=> 26 | var d = new nroComplejo(3,4); 27 | console.log(d.estado); 28 | 29 | //Esta bien?? 30 | -------------------------------------------------------------------------------- /apuntes/apuntes.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,a4paper]{article} 2 | 3 | \input{header} 4 | 5 | \begin{document} 6 | \title{Apuntes Paradigmas de Lenguajes de Programación} 7 | 8 | \date{\today} 9 | 10 | \author{Gianfranco Zamboni} 11 | \pagenumbering{Alph} 12 | \begin{titlepage} 13 | \maketitle 14 | \thispagestyle{empty} 15 | \tableofcontents 16 | \end{titlepage} 17 | \pagenumbering{arabic} 18 | 19 | \newpage 20 | \setcounter{page}{1} 21 | 22 | \input{secciones/introduccion} 23 | \newpage 24 | \part{Paradigma Funcional} 25 | 26 | \input{secciones/programacion_funcional} 27 | 28 | \newpage 29 | \input{secciones/calculo_lambda} 30 | 31 | \newpage 32 | \input{secciones/inferencia_de_tipos} 33 | 34 | \newpage 35 | \input{secciones/subtipado} 36 | 37 | \newpage 38 | \part{Paradigma orientado a objetos} 39 | \input{secciones/objetos} 40 | 41 | \newpage 42 | \input{secciones/clasificacion} 43 | 44 | \newpage 45 | \input{secciones/prototipado} 46 | 47 | \newpage 48 | \part{Paradigma Lógico} 49 | \input{secciones/programacion_logica} 50 | \input{secciones/logica_propocisional} 51 | 52 | \newpage 53 | \input{secciones/logica_primer_orden} 54 | 55 | \newpage 56 | \input{secciones/resolucion_sld} 57 | \appendix 58 | \newpage 59 | \input{secciones/apendices} 60 | 61 | \end{document} -------------------------------------------------------------------------------- /soluciones_haskell_js_prolog/Practica0.hs: -------------------------------------------------------------------------------- 1 | module Practica0 where 2 | 3 | import Data.List 4 | 5 | -- AUXILIARES -- 6 | 7 | divisores :: Int -> [Int] 8 | divisores x = [ y | y <- [1..x], x `mod` y == 0 ]; 9 | 10 | esPrimo :: Int -> Bool 11 | esPrimo x = length (divisores x) == 2 12 | 13 | -- Ejercicio 2 -- 14 | valorAbsoluto :: Float -> Float 15 | valorAbsoluto x | x < 0 = -x 16 | | otherwise = x 17 | 18 | bisiesto :: Int -> Bool 19 | bisiesto x = (x `mod` 4) == 0 20 | 21 | factorial :: Int -> Int 22 | factorial 1 = 1 23 | factorial x = x * factorial (x-1) 24 | 25 | cantDivisoresPrimos :: Int -> Int 26 | cantDivisoresPrimos x = length (filter esPrimo (divisores x)) 27 | 28 | -- Ejercicio 3 -- 29 | inverso :: Float -> Maybe Float 30 | inverso 0 = Nothing 31 | inverso x = Just (1/x) 32 | 33 | aEntero :: Either Int Bool -> Int 34 | aEntero (Left x) = x 35 | aEntero (Right x) | x == True = 1 36 | | otherwise = 0 37 | 38 | -- Ejercicio 4 -- 39 | limpiar :: String -> String -> String 40 | limpiar xs ys = [ y | y <- ys, not(elem y xs) ] 41 | 42 | difPromedio :: [Float] -> [Float] 43 | difPromedio xs = map (\y -> y - promedio xs) xs 44 | where promedio xs = (sum xs) / (genericLength xs) 45 | 46 | todosIguales :: [Int] -> Bool 47 | todosIguales xs = foldr (\y rec -> (y == (head xs)) && rec) True xs 48 | 49 | -- Ejercicio 5 -- 50 | data AB a = Nil | Bin (AB a) a (AB a) deriving Show 51 | 52 | vacioAB:: AB a -> Bool 53 | vacioAB Nil = True 54 | vacioAB (Bin _ _ _) = False 55 | 56 | negacionAB :: AB Bool -> AB Bool 57 | negacionAB Nil = Nil 58 | negacionAB (Bin l x r) = Bin (negacionAB l) (not x) (negacionAB r) 59 | 60 | productoAB :: AB Int -> Int 61 | productoAB Nil = 1 62 | productoAB (Bin l x r) = x * (productoAB l) * (productoAB r) -------------------------------------------------------------------------------- /apuntes/secciones/objetos.tex: -------------------------------------------------------------------------------- 1 | \section{Objetos y el modelo de cómputo} 2 | 3 | En el parádigma orientado a objetos, todo programa es una simulación representada por una entidad u \textbf{objeto} que asocia los objetos físicos o conceptuales de un dominio del mundo real en objetos del dominio del programa. Estos objetos tienen las características y capacidades del mundo real que nos interesa modelar y se comunican, entre si, a través de intercambios de mensajes. 4 | 5 | Los mensajes intercambiados son solicitudes para que, el objeto \textbf{receptor} del mismo, lleve a cabo una de sus operaciones. El \textbf{receptor} determinara si puede llevarla a cabo y, si puede hacerlo la ejecutará. 6 | 7 | \subsection{Objetos} 8 | Un objeto es una entidad del programa que puede recibir un conjunto de mensajes (al que llamaremos \textbf{interfaz} o \textbf{protocolo}) que le permiten determinar como llevar a cabo ciertas operaciones. Internamente, estará compuesto por: 9 | \begin{itemize} 10 | \item Un conjunto de \textbf{colaboradores internos} (tambien llamados \textbf{atributos} o \textbf{variables internas}) que determinan su \textbf{estado interno}. 11 | \item Un conjunto de \textbf{métodos} que describen (implementan) las operaciones que puede realizar y, si estas afectan a su estado interno, como lo hacen. 12 | \end{itemize} 13 | 14 | \paragraph{Principio de ocultamiento de la información} 15 | El estado de un objeto es \textbf{privado} y solamente puede ser consultado o modificado por sus propios métodos. Su implementación no depende de los detalles de implementación de otros objetos y la única forma que tenemos de interactuar con él, es enviándole los mensajes definidos en su interfaz. 16 | 17 | \paragraph{Method dispatch} Es la forma mediante la cuál, un proceso, establece la asociación entre el mensaje y el método a ejecutar. Es decir, cuando un objeto recibe un mensaje, el \textbf{method dispatch} se encarga de hallar la \textbf{declaración del método} que se pretende ejecutar. 18 | 19 | \paragraph{Corrientes de organización} 20 | Por lo general, tratamos de agrupar los objetos en conjuntos compuestos por objetos que se comportan de manera similar para conseguir programas más concisos. Esto se puede hacer de dos formas: Mediante clasifiación o mediante prototipado. -------------------------------------------------------------------------------- /apuntes/header.tex: -------------------------------------------------------------------------------- 1 | \usepackage[spanish]{babel} 2 | \usepackage[utf8]{inputenc} 3 | 4 | 5 | \usepackage[pdftex, 6 | pdfauthor={Gianfranco Zamboni}, 7 | pdftitle={Paradigmas de Lenguajes de Programación}, 8 | pdfsubject={}, 9 | pdfkeywords={Resumen , Computacion, FCEyN, UBA, Paradigmas de Lenguajes de Programación, Imperativo, Funcional, Cálculo Lambda, Programación Orientada a Objetos, Objetos, Programación Lógica, Recursion, Tipado, Sintaxis, Subtipado, Semantica, Programacion orientada a objetos}, 10 | pdfproducer={Latex with hyperref}, 11 | pdfcreator={pdflatex}, 12 | pdfencoding = auto]{hyperref} 13 | 14 | \usepackage{geometry} 15 | \usepackage{amsmath} 16 | \usepackage{amssymb} 17 | \usepackage{fancyhdr} 18 | \usepackage{forest} 19 | \usepackage{tikz} 20 | \usepackage{minted} 21 | \usepackage{multicol} 22 | \usepackage{mathabx} 23 | \usepackage{bussproofs} 24 | 25 | \geometry{ 26 | includeheadfoot, 27 | margin=2.54cm 28 | } 29 | 30 | \usemintedstyle{vs} 31 | 32 | \pagestyle{fancy} 33 | \fancyhf{} 34 | \renewcommand{\sectionmark}[1]{\markright{\thesection\ - #1}} 35 | \fancyhead[LO]{Sección \rightmark } 36 | \fancyhead[RO]{\small{Paradigmas de Lenguajes de Programación}} 37 | \fancyfoot[CO]{\thepage} 38 | \renewcommand{\headrulewidth}{0.5pt} 39 | \renewcommand{\footrulewidth}{0.5pt} 40 | \setlength{\headsep}{1cm} 41 | \setlength{\headheight}{13.07225pt} 42 | 43 | \renewcommand{\baselinestretch}{1.2} % line 44 | 45 | \setcounter{tocdepth}{2}% Allow only \chapter in ToC 46 | 47 | 48 | \newenvironment{centrado} 49 | { 50 | \begin{center} 51 | \begin{minipage}{0.9\textwidth} 52 | } 53 | { 54 | \end{minipage} 55 | \end{center} 56 | } 57 | 58 | \newcommand{\rel}{\ensuremath{\mathcal{R}}} 59 | 60 | \newcommand{\equalDef}{\overset{def}{=}} 61 | \newcommand{\equalDot}{\overset{\cdot}{=}} 62 | 63 | \newcommand{\lambdaAbs}[3]{\lambda #1: #2 . #3} 64 | \newcommand{\lambdaAssign}[2]{#1~:=~#2} 65 | \newcommand{\lambdaApp}[2]{#1~#2} 66 | \newcommand{\lambdaIf}[3]{if~ #1~ then~ #2~ else~ #3} 67 | \newcommand{\lambdaTrue}{true} 68 | \newcommand{\lambdaFalse}{false} 69 | \newcommand{\lambdaLet}[4]{let~#1:#2 = #3~in~#4} 70 | \newcommand{\lambdaRef}[1]{ref~#1} 71 | \newcommand{\lambdaVar}[1]{#1} 72 | \newcommand{\lambdaValue}[1]{\color{red}#1\color{black}} 73 | \newcommand{\lambdaFix}[1]{fix~#1} 74 | 75 | \newcommand{\lambdaAbsI}[2]{\lambda #1. #2} 76 | \newcommand{\lambdaLetI}[3]{let~#1 = #2~in~#3} 77 | 78 | 79 | 80 | \newcommand{\blue}[1]{\color{blue}#1\color{black}} 81 | \newcommand{\replaceBy}[3]{#1\{#2\leftarrow#3\}} 82 | \newcommand{\multiReplaceBy}[2]{#1\{#2\}} 83 | 84 | \newcommand{\judgeType}[3]{#1\triangleright #2 : #3} 85 | \newcommand{\judgeTypeS}[3]{#1\mapsto #2 : #3} 86 | 87 | 88 | \newcommand{\OOAtributo}[3]{#1 = \varsigma(#2)#3} 89 | \newcommand{\OORedefinicion}[3]{#1 \leftleftharpoons \varsigma(#2)#3} 90 | \newcommand{\OOReduccion}[2]{#1 \longrightarrow #2} 91 | \newcommand{\OORep}[1]{\green{[[}#1\green{]]}} 92 | 93 | \newenvironment{scprooftree} 94 | {\leavevmode\hbox\bgroup} 95 | {\DisplayProof\egroup} 96 | 97 | \tikzset{ 98 | every leaf node/.style={text=red, align=center}, 99 | every tree node/.style={text=blue, align=center}, 100 | } 101 | 102 | \forestset{tikzQtree/.style={for tree={if n children=0{ 103 | node options=every leaf node/.try}{node options=every tree node/.try}, text centered}}} 104 | 105 | \forestset{resolucion/.style={for tree={ grow=north, calign=first }}} 106 | 107 | \DeclareMathOperator{\Erase}{Erase} 108 | 109 | \newcommand{\List}[1]{[~]_{#1}} 110 | \newcommand{\lambdaListCase}[3]{\text{case } #1 \text{ of } \{[~]\leadsto#2~|~h::t\leadsto#3\}} 111 | \newcommand{\lambdaListFold}[3]{\text{foldr } #1 \text{ base }\leadsto#2;~\text{rec}(h, r)\leadsto#3} 112 | 113 | \newcommand{\WFunc}{\mathbb{W}} 114 | 115 | \newcommand{\red}[1]{{\color{red}#1}}%\renewcommand{\appendixtocname}{Apéndices} 116 | \newcommand{\green}[1]{{\color{green!60!black}#1}}%\renewcommand{\appendixpagename}{Apéndices} 117 | 118 | %lenguajesInline 119 | \newcommand{\haskell}[1]{\mintinline{haskell}{#1}} 120 | \newcommand{\javascript}[1]{\mintinline{javascript}{#1}} 121 | \newcommand{\prolog}[1]{\mintinline{prolog}{#1}} -------------------------------------------------------------------------------- /practicas_solucion/header.tex: -------------------------------------------------------------------------------- 1 | %% Packages 2 | \usepackage[pdftex, 3 | pdfauthor={Gianfranco Zamboni}, 4 | pdftitle={Resumen: Paradigmas de Lenguajes de Programación}, 5 | pdfsubject={}, 6 | pdfkeywords={Resumen , Computacion, FCEyN, UBA, Paradigmas de Lenguajes de Programación, Imperativo, Funcional, Cálculo Lambda, Programación Orientada a Objetos, Objetos, Programación Lógica}, 7 | pdfproducer={Latex with hyperref}, 8 | pdfcreator={pdflatex}]{hyperref} 9 | 10 | \usepackage{a4wide} % márgenes un poco más anchos que lo usual 11 | \usepackage{amsmath} 12 | \usepackage{amssymb} 13 | \usepackage[titletoc,toc,page]{appendix} 14 | \usepackage[spanish]{babel} 15 | \usepackage{bussproofs} 16 | \usepackage{enumerate} 17 | 18 | \usepackage{graphicx} 19 | \usepackage[utf8]{inputenc} % para poder usar tildes en archivos UTF-8 20 | \usepackage{lscape} 21 | \usepackage{mathabx} 22 | \usepackage{minted} 23 | \usepackage{multicol} 24 | \usepackage{pifont} 25 | \usepackage[table]{xcolor} 26 | 27 | %Para crear los arboles de sintaxis y demostraciones 28 | \usepackage{forest} 29 | 30 | 31 | % Styles 32 | 33 | \rowcolors{2}{gray!10}{white} 34 | 35 | \usemintedstyle{friendly} 36 | 37 | \setlength{\columnsep}{5mm} 38 | 39 | \ifthenelse{\paperwidth < \paperheight}{\input{page.layout}}{\input{landscape.page.layout}} 40 | 41 | \forestset{resolucion/.style={for tree={ grow=north, calign=first}}} 42 | 43 | % Enviroments 44 | 45 | \newenvironment{centrado} 46 | { 47 | \begin{center} 48 | \begin{minipage}{0.8\textwidth} 49 | } 50 | { 51 | \end{minipage} 52 | \end{center} 53 | } 54 | 55 | \newenvironment{centrado2} 56 | { 57 | \begin{center} 58 | \begin{minipage}{0.4\textwidth} 59 | } 60 | { 61 | \end{minipage} 62 | \end{center} 63 | } 64 | 65 | 66 | \newenvironment{scprooftree} 67 | {\leavevmode\hbox\bgroup} 68 | {\DisplayProof\egroup} 69 | 70 | %Comandos 71 | 72 | % Simbolos Utiles 73 | \newcommand{\alphaEq}[1]{\underset{#1}{\overset{\alpha-eq}{\leadsto}}} 74 | 75 | \newcommand{\comma}{{,}} % Para usar dentro de los bosques. 76 | 77 | 78 | \newcommand{\equalDef}{\overset{def}{=}} 79 | 80 | \newcommand{\goesTo}[2]{\underset{#2}{\overset{#1}{\leadsto}}} 81 | 82 | \newcommand{\List}[1]{[~]_{#1}} 83 | \newcommand{\longTo}{\longrightarrow} 84 | 85 | \newcommand{\reduceTo}[1]{\underset{#1}{\to}} 86 | \newcommand{\rel}{\ensuremath{\mathcal{R}}} 87 | \newcommand{\replaceBy}[3]{#1\{#2\leftarrow#3\}} 88 | \newcommand{\multiReplaceBy}[2]{#1\{#2\}} 89 | 90 | 91 | \newcommand{\WFunc}{\mathbb{W}} 92 | 93 | \newcommand{\xmark}{\ding{55}}% 94 | 95 | %Colores 96 | \newcommand{\blue}[1]{{\color{blue}#1}} 97 | \newcommand{\red}[1]{{\color{red}#1}} 98 | \newcommand{\green}[1]{{\color{green}#1}} 99 | 100 | %Calculo Lambda 101 | \newcommand{\lambdaAbs}[3]{\lambda #1: #2 \text{.} #3} 102 | \newcommand{\lambdaApp}[2]{#1~#2} 103 | \newcommand{\lambdaAssign}[2]{#1~:=~#2} 104 | \newcommand{\lambdaFalse}{false} 105 | \newcommand{\lambdaFix}[1]{\text{fix } #1} 106 | \newcommand{\lambdaIf}[3]{\text{if } #1 \text{ then } #2 \text{ else } #3} 107 | \newcommand{\lambdaLet}[4]{\text{let}~#1:#2 = #3~in~#4} 108 | \newcommand{\lambdaRef}[1]{\text{ref}~#1} 109 | \newcommand{\lambdaTrue}{true} 110 | \newcommand{\lambdaValue}[1]{{\color{red}#1}} 111 | \newcommand{\lambdaVar}[1]{#1} 112 | 113 | \newcommand{\lambdaAbsI}[2]{\lambda #1\text{.} #2} 114 | \newcommand{\lambdaLetI}[3]{let~#1 = #2~in~#3} 115 | 116 | \newcommand{\lambdaLetrec}[3]{\text{letrec } #1 = #2 \text{ in }~#3} 117 | 118 | \newcommand{\lambdaListCase}[3]{\text{case } #1 \text{ of } \{[~]\leadsto#2~|~h::t\leadsto#3\}} 119 | \newcommand{\lambdaListFold}[3]{\text{foldr } #1 \text{ base }\leadsto#2;~\text{rec}(h, r)\leadsto#3} 120 | 121 | \newcommand{\falla}{\red{\texttt{falla}}} 122 | 123 | \newcommand{\judgeType}[3]{#1\triangleright #2 : #3} 124 | \newcommand{\judgeTypeS}[3]{#1\mapsto #2 : #3} 125 | 126 | 127 | %Calculo objetos 128 | \newcommand{\OOAtributo}[3]{#1 = \varsigma(#2)#3} 129 | \newcommand{\OORedefinicion}[2]{#1 \leftleftharpoons #2} 130 | \newcommand{\OOReduccion}[2]{#1 \longrightarrow #2} 131 | \newcommand{\OOMetodo}[2]{\varsigma(#1)#2} 132 | \newcommand{\OORep}[1]{\green{[[}#1\green{]]}} 133 | 134 | 135 | %lenguajesInline 136 | \newcommand{\haskell}[1]{\mintinline{haskell}{#1}} 137 | \newcommand{\javascript}[1]{\mintinline{javascript}{#1}} 138 | \newcommand{\prolog}[1]{\mintinline{prolog}{#1}} 139 | 140 | 141 | -------------------------------------------------------------------------------- /apuntes/secciones/clasificacion.tex: -------------------------------------------------------------------------------- 1 | \section{Clasificación} 2 | Se usan \textbf{clases} que modelan \textbf{conceptos abstractos} del dominio del problema a resolver y definen el comportamiento y la forma de un conjunto de objetos (sus \textbf{instancias}). Todo \textbf{objeto} es una instancia de una clase. 3 | 4 | \paragraph{Componentes de una clase} 5 | Todas las clases tienen un \textbf{nombre} que usado para referenciarse a la misma. Dentro de ellas se definen las variables de instancias (colaboradores internos) de los objetos) y los métodos que saben responder esas instancias (sus nombres, sus parámetros y su cuerpo). 6 | 7 | \subsection{Self/This} 8 | Todas las clases tienen definida una pseudovariable que, durante la evaluación de un método, referencia al receptor del mensaje que activó dicha evaluación. No puede ser modificada por medio de una asignación y se liga automáticamente al receptor cuando comienza la evaluación del método. 9 | 10 | \begin{minted}{smalltalk} 11 | !classDefinition: #Node 12 | instanceVariableNames: 'leftchild, rightchild' 13 | ... 14 | sum: 15 | ^ (self leftchild) sum + (self rightchild) ! ! 16 | 17 | !classDefinition: #Leaf 18 | instanceVariableNames: 'value' 19 | ... 20 | sum: 21 | ^self value ! ! 22 | 23 | \end{minted} 24 | 25 | Vemos que los métodos acceden a sus variables de instancia, enviándose a si mismos el mensaje asociado a cada una de ellas. En muchos lenguajes, para facilitar la escritura de un programa, la mención de \texttt{self} se hace implícitamente. 26 | 27 | \subsection{Jerarquía de clases} 28 | Cuando escribimos un programa en este paradigma, es común que creemos nuevas clases que extiendan a las ya existentes con nuevas variables de instancia o clase o que modifiquen el comportameiento de unos o varios métodos. 29 | 30 | Para evitar tener que escribir toda una clase de cero, hacemos que la clase que estamos creando \textbf{herede} los atributos y los métodos de la clase pre-existente (la \textbf{super-clase}) que queremos extender. De esta forma, la nueva clase tendrá todo lo que tenía la super-clase y, además, las modificaciones que nosotros querramos agregarle. 31 | 32 | La herencia define una relación transitiva. Si una clase $A$ tiene como super-tipo a otra clase $B$ y $C$ es super-tipo de $B$, entonces $C$ tambien es super-tipo de $A$. Llamaremos \textbf{ancestros} a todos los supertipos de $A$ y \textbf{descendientes} a todos los tipos que tienen a $A$ como ancestro. 33 | 34 | \subsection{Tipos de herencia} 35 | Hay dos tipos de herencia: \textbf{simple} y \textbf{múltiple}. La herencia simple permite que una clase tenga una única clase padre, mientras que la herencia múltiple deja que una clase tenga varios padres. 36 | 37 | Además, todas las clases deben heredar de una clase \texttt{Object} que es la raíz del árbol o cadena de herencias. 38 | 39 | La mayoría de los lenguajes orientados a objetos utilizan la herencia simple ya que la herencia múltiple complica el proceso de method dispath (que asocia los mensajes de un objeto con sus respectivos métodos). 40 | 41 | Supongamos que tenemos dos clases $A$ y $B$ incomparables y una clase $C$ que es subclase de $A$ y $B$ simultaneamente. Si $A$ y $B$ definen (o heredan) dos métodos diferentes para un mismo mensaje $m$, entonces cuando enviemos dicho mensaje a $C$ deberemos decidir cuál de los dos métodos asociados debemos evaluar. Esta selección se puede realizar de dos formas: 42 | \begin{itemize} 43 | \item Estableciendo un \textbf{orden de búsqueda} sobre las superclases de un clase asignando un nivel de prioridad a cada una de ellas. 44 | \item U obligando al programador a \textbf{redefinir} el método en $C$ si $C$ hereda dos métodos distintos para el mismo mensaje. 45 | \end{itemize} 46 | 47 | \subsubsection{Method Dispatch} 48 | 49 | Como dijimos, el \textbf{method Dispatch} es el método mediante el cual asociamos un mensaje a su método correspondiente en el objeto. Por lo general, este método se realiza de manera dinámica, es decir se realizan durante tiempo de ejecución. Sin embargo, dependiendo del contexto, hay situaciones en las que realizar este proceso de manera estática es necesario. 50 | 51 | Un ejemplo de esto, es cuando el lenguaje nos permite hacer uso de \texttt{super}, una pseudovariable que \textbf{referencia al objeto que recibe el mensaje} y \textbf{cambia} su proceso de activación al momento de recibirlo. 52 | Cuando usamos una expresión de la forma \texttt{super msg} en el cuerpo de un método $m$, el \textbf{method lookup} (la búsqueda del método realizada por el method dispath), comienze a realizarse desde el padre de la \textbf{clase anfitriona} de m. 53 | 54 | Algunos lenguajes, además, nos permiten pasarle como parámetro una clase a partir de la cual se debe empezar la búsqueda de la siguiente forma: \texttt{super[A] msg}, siempre y cuando $A$ sea un ancestro de la clase anfitriona del método. -------------------------------------------------------------------------------- /practicas_solucion/practica_0.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,a4paper]{article} 2 | \input{header} 3 | \setcounter{section}{0} 4 | 5 | \begin{document} 6 | 7 | \title{PLP - Práctica 0: Pre-Práctica de Programación Funcional} 8 | 9 | \date{\today} 10 | 11 | \author{Gianfranco Zamboni} 12 | 13 | \maketitle 14 | \setcounter{page}{1} 15 | 16 | \subsection{Ejercicio 1} 17 | \haskell{null :: Foldable t => t a -> Bool} indica si una estructura está vacía. El tipo a debe ser de la clase Foldable, esto es, son tipos a los que se les puede aplicar la función foldr. La notación "t a" indica que es un tipo parámetrico, es decir, un tipo t que usa a otro tipo a, por ejemplo, si le pasamos a la función una lista de enteros, entonces a = Int y t = [Int] 18 | 19 | \vspace*{5mm} 20 | \haskell{head :: [a] -> a} devuelve el primer elemento de una lista. 21 | 22 | \vspace*{5mm} 23 | \haskell{tail :: [a] -> [a]} devuelve los últimos elementos de una lista (todos los elementos, salvo el primero). 24 | 25 | \vspace*{5mm} 26 | \haskell{init :: [a] -> [a]} devuelve los primeros elementos de una lista (todos los elementos salvo el último). 27 | 28 | \vspace*{5mm} 29 | \haskell{last :: [a] -> a} devuelve el último elemento de una lista. 30 | 31 | 32 | \vspace*{5mm} 33 | \haskell{take :: Int -> [a] -> [a]} devuelve los primeros n elementos de una lista 34 | 35 | \vspace*{5mm} 36 | \haskell{drop :: Int -> [a] -> [a]} devuelve los últimos n elementos de una lista 37 | 38 | \vspace*{5mm} 39 | \haskell{(++) :: [a] -> [a] -> [a]} concatena dos listas 40 | 41 | \vspace*{5mm} 42 | \haskell{concat :: Foldable t => t [a] -> [a]} concatena todas las listas de un contenedor de listas que soporte la operación foldr. 43 | 44 | \vspace*{5mm} 45 | \haskell{(!!) :: [a] -> Int -> a} devuelve el elemento de una lista 46 | \haskell{l} que se encuentra en la \haskell{n}-ésima posición. La numeración comienza desde 0. 47 | 48 | \vspace*{5mm} 49 | \haskell{elem :: (Eq a, Foldable t) => a -> t a -> Bool}: Dada una estructura T que soporta la operación foldr y que almacene elementos del tipo a que puedan ser comparados por medio de la igualdad y dado un elemento A de ese tipo, indica si A aparecen en T. 50 | 51 | \subsection{Ejercicio 2} 52 | \begin{centrado} 53 | \begin{minted}[breaklines]{haskell} 54 | -- a) La función abs de Prelude ya hace esto 55 | valorAbsoluto :: Float -> Float 56 | valorAbsoluto x | x < 0 = -x 57 | | otherwise = x 58 | \end{minted} 59 | \end{centrado} 60 | \begin{centrado} 61 | \begin{minted}[breaklines]{haskell} 62 | -- b) 63 | bisiesto :: Int -> Bool 64 | bisiesto x = (x `mod` 4) == 0 65 | \end{minted} 66 | \end{centrado} 67 | \begin{centrado} 68 | \begin{minted}[breaklines]{haskell} 69 | --c) 70 | factorial :: Int -> Int 71 | factorial 1 = 1 72 | factorial x = x * factorial (x-1) 73 | \end{minted} 74 | \end{centrado} 75 | \begin{centrado} 76 | \begin{minted}[breaklines]{haskell} 77 | cantDivisoresPrimos :: Int -> Int 78 | cantDivisoresPrimos x = length (filter esPrimo (divisores x)) 79 | \end{minted} 80 | \end{centrado} 81 | 82 | \begin{centrado} 83 | \begin{minted}[breaklines]{haskell} 84 | -- Auxiliares 85 | 86 | esPrimo :: Int -> Bool 87 | esPrimo x = length (divisores x) == 2 88 | 89 | divisores :: Int -> [Int] 90 | divisores x = [ y | y <- [1..x], x `mod` y == 0 ]; 91 | \end{minted} 92 | \end{centrado} 93 | 94 | \subsection{Ejercicio 3} 95 | \begin{centrado} 96 | \begin{minted}[breaklines]{haskell} 97 | --a) 98 | inverso :: Float -> Maybe Float 99 | inverso 0 = Nothing 100 | inverso x = Just (1/x) 101 | \end{minted} 102 | \end{centrado} 103 | 104 | \begin{centrado} 105 | \begin{minted}[breaklines]{haskell} 106 | -- b) 107 | aEntero :: Either Int Bool -> Int 108 | aEntero (Left x) = x 109 | aEntero (Right x) | x == True = 1 110 | | otherwise = 0 111 | \end{minted} 112 | \end{centrado} 113 | 114 | \subsection{Ejercicio 4} 115 | \begin{centrado} 116 | \begin{minted}[breaklines]{haskell} 117 | --a) 118 | limpiar :: String -> String -> String 119 | limpiar xs ys = [ y | y <- ys, not(elem y xs) ] 120 | \end{minted} 121 | \end{centrado} 122 | \begin{centrado} 123 | \begin{minted}[breaklines]{haskell} 124 | -- b) 125 | difPromedio :: [Float] -> [Float] 126 | difPromedio xs = map (\y -> y - promedio xs) xs 127 | where promedio xs = (sum xs) / (genericLength xs) 128 | \end{minted} 129 | \end{centrado} 130 | \begin{centrado} 131 | \begin{minted}[breaklines]{haskell} 132 | -- c) 133 | todosIguales :: [Int] -> Bool 134 | todosIguales = 135 | foldr (\y rec -> (y == (head xs)) 136 | && rec) True 137 | \end{minted} 138 | \end{centrado} 139 | 140 | \subsection{Ejercicio 5} 141 | \begin{centrado} 142 | \begin{minted}[breaklines, tabsize=4]{haskell} 143 | data AB a = Nil | Bin (AB a) a (AB a) 144 | \end{minted} 145 | \end{centrado} 146 | \begin{centrado} 147 | \begin{minted}[breaklines, tabsize=4]{haskell} 148 | -- a) 149 | vacioAB:: AB a -> Bool 150 | vacioAB Nil = True 151 | vacioAB (Bin _ _ _) = False 152 | \end{minted} 153 | \end{centrado} 154 | \begin{centrado} 155 | \begin{minted}[breaklines, tabsize=4]{haskell} 156 | -- b) 157 | negacionAB :: AB Bool -> AB Bool 158 | negacionAB Nil = Nil 159 | negacionAB (Bin l x r) = 160 | Bin (negacionAB l) (not x) (negacionAB r) 161 | \end{minted} 162 | \end{centrado} 163 | \begin{centrado} 164 | \begin{minted}[breaklines, tabsize=4]{haskell} 165 | -- c) 166 | productoAB :: AB Int -> Int 167 | productoAB Nil = 1 168 | productoAB (Bin l x r) = x * (productoAB l) * (productoAB r) 169 | \end{minted} 170 | \end{centrado} 171 | \end{document} 172 | -------------------------------------------------------------------------------- /apuntes/secciones/introduccion.tex: -------------------------------------------------------------------------------- 1 | Estos son los apuntes de la clases de PLP que se dio en Verano 2018. Prácticamente es una combinación de las diapositivas con lo que anoté de la teórica y las prácticas pero puede tener errores. En caso de ser así estaría bueno que me avisen así los corrijo. 2 | 3 | El tema de objetos en esta cursada se dió distinto a como se venía dando en cursadas anteriores. Vimos prototipado en vez de clasificación y además definimos el cálculo \(\varsigma\) análogo al cálculo \(\lambda\) en funcional. Los profesores no estaban seguros si estas modificaciones se iban a mantener o no durante las próximas cursadas. 4 | 5 | \section{Introducción} 6 | 7 | \paragraph{Paradigma} Marco filosófico y teórico de una escuela científica o disciplina en la que se formulan teorías, leyes y generalizaciones y se llevan a cabo experimentos que les dan sustento. 8 | 9 | \paragraph{Lenguaje de programación} Es un lenguaje usado para comunicar instrucciones a una computadora. Éstas describen los cómputos que debe llevar a cabo. 10 | 11 | Un lenguaje de programación es computacionalmente completo si puede expresar todas las funciones computables. 12 | 13 | \paragraph{Paradigma de lenguaje de programación} Marco filosófico y teórico en el que se formulan soluciones a problemas de naturaleza algorítmica. Lo entendemos como un estilo de programación en el que se escriben soluciones a problemas en términos de algoritmos. 14 | 15 | Su ingrediente básico es el modelo de cómputo, que es la visión que tiene el usuario de cómo se ejecutan sus programas. 16 | 17 | \subsection{Aspectos del lenguaje} 18 | 19 | \paragraph{Sintaxis} Descripción del conjunto de secuencias de símbolos considerados como programas válidos. Nos indica cuales son los símbolos del lenguaje y como combinarlos para que se les pueda dar una semántica. 20 | 21 | \subsubsection{Semántica} 22 | 23 | Descripción del significado de instrucciones y expresiones. Permite asignarle un significado a aquellas expresiones que formen parte de algún lenguaje, sea informal (e.g. Castellano) o formal (basado en técnicas matemáticas). 24 | 25 | Dependiendo el tipo de semántica que se esté utilizando, podremos interpretar un programa de distintas maneras: Si \(A\) es el dominio del problema y \(B\) el conjunto de posibles resultados, entonces: 26 | 27 | \paragraph{Semántica operacional} Se ve a un programa como un mecanismo que, dado un elemento \(a\in A \), sigue una sucesión de pasos para calcular el elemento \(b \in B\) que le corresponde a \(a\). 28 | 29 | \paragraph{Semántica axiomática} Interpreta a un programa como un conjunto de propiedades verdaderas que indican los estados que puede llegar a tomar ciertos valores. 30 | 31 | \paragraph{Semántica denotacional} Un programa es un valor matemático (función) que relaciona cada elemento de \(A\) (expresiones que lo componen) con un único elemento de \(B\) (significado de las expresiones). 32 | 33 | \subsubsection{Sistema de tipo} 34 | Es una herramienta que nos permite analizar código para prevenir errores comunes en tiempo de ejecución (e.g. evitar sumar booleanos, usar funciones con un número incorrecto de argumentos, etc). En general, requiere anotaciones de tipo en el código fuente. 35 | 36 | Además sirve para que la especificación de un programa sea más clara. 37 | 38 | Hay dos clases de análisis de tipos: 39 | \begin{itemize} 40 | \item \textbf{Estático}: En tiempo de compilación. 41 | \item \textbf{Dinámico}: En tiempo de ejecución. 42 | \end{itemize} 43 | 44 | \subsection{Paradigmas} 45 | \subsubsection{Paradigma Imperativo} 46 | 47 | \paragraph{Estado global} Se usan variables que representan celdas de memoria en distintos momentos del tiempo. Se usan para ir almacenando resultados intermedios del problema. 48 | 49 | \paragraph{Asignación} Es la acción que modifica las variables. 50 | 51 | \paragraph{Control de flujo} Es la forma que tenemos de controlar el orden y la cantidad de veces que se repite un cómputo dentro del programa. En este paradigma, la repetición de cómputos se basa en la iteración. 52 | 53 | \vspace*{5mm} 54 | 55 | Por lo general, los lenguajes de este paradigma son eficientes ya que el modelo de ejecución usado y la arquitectura de las computadoras (a nivel procesador) son parecidos. Sin embargo, el bajo nivel de abstracción que nos proveen hacen que la implementación de un problema sea difícil de entender. 56 | 57 | \subsubsection{Paradigma Funcional} 58 | No tiene un estado global. Un cómputo se expresa a través de la aplicación y composición de funciones y los resultados intermedios (salida de las funciones) son pasados directamente a otras funciones como argumentos. Todas las expresiones de este paradigma son tipadas y usa la recursión para repetir cómputos. 59 | 60 | Ofrece un alto nivel de abstracción, es declarativo, usa una matemática elegante y se puede usar razonamiento algebraico para demostrar correctitud de programas. 61 | 62 | \subsubsection{Paradigma Lógico} 63 | Los programas son predicados de la lógica proposicional y la computación esta expresada a través de proof search (probar que el predicado expresado es verdadero bajo ciertos axiomas). No existe un estado global y los resultados intermedios son pasados por unificación. La repetición se basa en la recursión. 64 | 65 | Ofrece un alto nivel de abstracción, es muy declarativo y, al ser predicados, tiene fundamentos lógicos robustos pero su ejecución es muy lenta. 66 | 67 | \subsubsection{Paradigma Orientado a Objetos} 68 | La computación se realiza a través del intercambio de mensajes entre objetos. Tiene dos enfoques: basados en clases o basados en prototipos. 69 | 70 | Ofrece alto nivel de abstracción y arquitecturas extensibles pero usa una matemática de programas compleja. 71 | -------------------------------------------------------------------------------- /apuntes/secciones/logica_propocisional.tex: -------------------------------------------------------------------------------- 1 | \section{Lógica Proposicional} 2 | \subsection*{Sintaxis} 3 | Dado un conjunto $\mathcal{V}$ de \textbf{variables proposionales} $P,P_0,P_1,\dots$, el conjunto de \textbf{formulas proposicionales (o proposiciones)} se define como: 4 | 5 | \begin{align*} 6 | A,B ~ :&= ~ P &&\text{una variable proposicional} \\ 7 | & |~ \lnot A &&\text{negación}\\ 8 | & |~ A \land B &&\text{conjunción}\\ 9 | & |~ A \lor B &&\text{disjunción}\\ 10 | & |~ A \supset B &&\text{implicación}\\ 11 | & |~ A \iff B &&\text{si y solo si} \\ 12 | \end{align*} 13 | 14 | 15 | \subsection{Semántica} 16 | 17 | Una \textbf{evaluación} es una función $v:\mathcal{V}\to{\textbf{T},\textbf{F}}$ que asigna valores de verdad a las variables proposicionales. Decimos que $v$ \textbf{satisface} una proposicón $A$ si $V\models A$ donde: 18 | 19 | \begin{align*} 20 | v \models P~&sii~v(P) = T\\ 21 | v \models \lnot A~&sii~ v \not{\models} A \text{ ($v$ no satisface $A$)}\\ 22 | v \models A \lor B~&sii~v \models A \text{ o } v\models B\\ 23 | v \models A \land B~&sii~v \models A \text{ y } v\models B\\ 24 | v \models A \supset B~&sii~v\not\models A \text{ o } v\models B\\ 25 | v \models A \iff B~&sii~(v\models A \text{ sii } v\models B)\\ 26 | \end{align*} 27 | 28 | Una proposición es \textbf{satisfactible} si existe una valuación $v$ tal que $v\models A$. Cuando no existe $v$ qua satisfaga $A$, decimos que $A$ es \textbf{insatisfactible}. 29 | 30 | Podemos extender estas definiciones a conjuntos de proposiciones. Si $S$ es un conjunto de proposiciones, entonces es \textbf{satisfactible} si existe una valuación $v$ tal que para todo $A\in S$, se tiene que $v\models A$. Y si no existe este $v$, entones $S$ es \textbf{insatisfactible}. 31 | 32 | Dada una proposición $A$, si vale que $v\models A$ para toda valuación $v$, entonces decimos que $A$ es una \textbf{tautología}. 33 | 34 | \paragraph{Literales} Un literal es una variable proposicional $P$ o su negación $\lnot P$. 35 | 36 | \subsubsection{Forma Normal Conjutiva (FNC)}\label{Logica::Proposicional::FNC} 37 | Diremos que una proposición $A$ está en FNC si es una conjunción de disjunciones de literales. Es decir si tiene la siguiente forma: 38 | 39 | $$C_1 \land\dots\land C_n$$ 40 | 41 | donde cada \textbf{claúsula} $C_i$ es una disyunción de literales: 42 | 43 | $$B_{i1}\lor\dots\lor B_{in_i}$$ 44 | 45 | \paragraph{Teorema:} Para toda proposición $A$ puede hallarse una proposición $A'$ en FNC que es lógicamente equivalente a $A$. 46 | 47 | \paragraph{Nota:} $A$ es lógicamente equivalente a $B$ si y solo si la proposición $A\iff B$ es una tautología. 48 | 49 | \subsubsection*{Notación conjuntista} 50 | Dada la siguiente expresión en forma normal conjuntiva: 51 | 52 | $$(A\lor B)\land(A\lor \lnot A) \land (\lnot B \lor \lnot B) \land (B\lor A)\land (C\lor D)$$ 53 | 54 | Trataremos de escribirla de manera más simple. Lo primero que notamos es que $(A \lor \lnot A)$ es una tautología, ya que siempre vale una de las dos propocisiones. Entonces podemos eliminar esta clausula sin modificar su valor de verdad. 55 | 56 | $$(A\lor B)\land (\lnot B \lor \lnot B) \land (B\lor A)$$ 57 | 58 | Además, $(\lnot B \lor \lnot B) \iff \lnot B$ ($\lor$ es idempotente): 59 | 60 | $$(A\lor B)\land \lnot B \land (B\lor A)$$ 61 | 62 | Como $\lor$ también es conmutativo, sabemos que $(A \lor B) \iff (B \lor A)$ por lo que podemos eliminar una de las dos: 63 | 64 | $$(A\lor B)\land \lnot B$$ 65 | 66 | Logramos escribir la proposición original con una expresión equivalente con todas las clausulas distintas. Donde las clausula son $C_1 = (A\lor B)$ y $C_2 = \lnot B$. 67 | 68 | Cuando sucede esto, podemos representar la proposición como un conjunto de clausulas \\ $\{C_1,\dots,C_n\}$ donde cada clausula $C_i$ es un conjunto de literales. Es decir que la expresión del ejemplo puede ser escrita de la siguiente manera: 69 | 70 | $$\{\{A,B\},\{\lnot B\}\}$$ 71 | 72 | \subsection{Validez por refutación} 73 | 74 | \textbf{Teorema:} Una proposición $A$ es una tautología sii $\lnot A$ es insastisfactible. 75 | 76 | \vspace*{5mm} 77 | Entonces, dada una proposición $A$, si probramos que $\lnot A$ es insatisfactible podemos probar que $A$ es una tautología. A pesar de que hay varias técnicas para hacer esto, vamos a concentrarnos en el método de \textbf{resolución} que fue introducipo por Alan Robinson en 1965. 78 | 79 | Este método es simple de implementar y hace uso de una única regla de inferencia (\textbf{la regla de resolución}) para demostrar que una fórmula en forma normal conjuntiva es insatisfactible. 80 | 81 | \subsubsection{Principios fundamentales} 82 | El método, usa la regla de inferencia para expandir un conjunto $S$ hasta que el mismo contenga dos clausulas que se niegen entre si. Para esto, hace uso de la siguiente tautología: 83 | 84 | $$(A\lor P)\land (B\lor \lnot P) \iff (A\lor P)\land (B\lor \lnot P) \land (A \lor B)$$ 85 | 86 | \begin{centrado} 87 | \paragraph{Demostración} Queremos ver que $(A\lor P)\land (B\lor \lnot P)$ y $(A\lor P)\land (B\lor \lnot P) \land (A \lor B)$ son equivalentes: 88 | 89 | Si $(A\lor P)\land (B\lor \lnot P)$ es satisfactible, entonces valen las dos clausulas de la proposición. Por la primer clausula vale que $A$ es satisfactible o $P$ lo és. Si $P$ es satisfactible, entonces $B$ es satisfactible, pues $\lnot P$ no lo es, entonces vale $(A\lor B)$. 90 | 91 | Si $P$ no es satisfactible, entonces $A$ debe serlo para que $(A\lor P)$ lo sea y, además $\lnot P$ es satisfactible por lo que la segunda clausula tambien lo és y como $A$ es satisfactible vale $(A\lor B)$. 92 | 93 | Por otro lado, si $A$ y $B$ no son satisfactibles, entonces $(A\lor P)\land (B\lor \lnot P)$ no es satisfactible pues, para que lo sea, tendrían que valer $P$ y $\lnot P$ al mismo tiempo. 94 | 95 | Entonces, ambas expresiones son equivalentes. 96 | 97 | \end{centrado} 98 | 99 | Este resultado nos permite asegurar que los conjuntos de claúsulas 100 | $$\{C_1,\dots,C_n,\{A,P\}, \{B,\lnot P\}\}\hspace*{5mm}y\hspace*{5mm}\{C_1,\dots,C _n,\{A,P\}, \{B,\lnot P\}, \{A,B\}\}$$ 101 | son equivalentes. Y si uno de ellos es insatisfactible, entonces el otro lo és. 102 | 103 | Cuando esto suceda, diremos que la cláusula $\{A,B\}$ es la \textbf{resolvente} de las claúsulas $\{A,P\}$ y $\{B,\lnot P\}$. Además generalizamos la definicion para clausulas con más de dos literales: 104 | 105 | \paragraph{Notación:} Dado un literal $L$, su opuesto $\overline{L}$ se define como 106 | \begin{itemize} 107 | \item $\lnot P$ si $L=P$ 108 | \item $P$ si $L=\lnot P$. 109 | \end{itemize} 110 | 111 | 112 | \vspace*{5mm} 113 | Dadas dos cláusulas $C_1$, $C_2$, una claúsula $C$ se dice \textbf{resolvente de $C_1$ y $C_2$} si y solo si, para algún literal $L$, $L\in C_1$ y $\overline{L}\in C_2$ y $C = (C_1-\{L_1\})\cup(C_2-\{\overline{L}\})$. Notaremos la regla de resolución como 114 | $$\frac{C_1 = \{A_1,\dots,A_m,L\}\hspace*{5mm} C_2 = \{B_1,\dots,B_m, \overline{L}\}}{C = \{A_1,\dots,A_m, B_1,\dots,B_n\}}$$ 115 | 116 | 117 | El método de resolución ira agregando resolventes (que todavía no pertenezcan) al conjunto hasta conseguir un conjunto que contenga dos cláusulas de la forma $\{P\}$ y $\{\lnot P\}$ cuya resolvente es la cláusula vacía notada como $\Box$. Cuando esto suceda, diremos que conseguimos una \textbf{refutación}. 118 | 119 | Entonces, en resumen, el método de resolución trata de construir una secuencia de conjuntos claúsales que termina en una refutación y, si lo logra, como todos los conjuntos de la secuencia son equivalentes el conjunto original no es satisfactible. 120 | 121 | El método siempre termina, ya que las resolventes agregados se forman con los literales distintos que aparecen en el conjunto de partida y hay una cantidad finitas de literales en dicho conjunto. 122 | 123 | En el peor de los casos, la regla de resolución podrá generar una nueva cláusula por cada combinación diferente de literales distintos de $S$. 124 | 125 | \paragraph{Teorema} Dado un conjunto finito $S$ de cláusulas, $S$ es insatisfactible si y solo si tiene una refutación. 126 | 127 | \subsubsection*{Ejemplo de resolución} 128 | 129 | Vamos a probar que $\{ \{P,Q\},\{P,\lnot Q\},\{\lnot P, Q\},\{\lnot P, \lnot Q\}\}$ es insatisfactible. Armamos la primer resolvente con $\{P,Q\}$,$\{P,\lnot Q\}$ que nos queda $C = \{P\}$, entonces el nuevo conjunto es: 130 | $$\{ \{P,Q\},\{P,\lnot Q\},\{\lnot P, Q\},\{\lnot P, \lnot Q\}, \{P\} \}$$ 131 | Armamos la segunda resolvente con $\{\lnot P, Q\}$ y $\{\lnot P, \lnot Q\}$ entonces $C_1 = \{\lnot P\}$: 132 | $$\{ \{P,Q\},\{P,\lnot Q\},\{\lnot P, Q\},\{\lnot P, \lnot Q\}, \{P\}, \{\lnot P\} \}$$ 133 | Y por útlimo usamos $\{P\}$ $\{\lnot P\}$ y agregamos la resolvente $\Box$ al conjunto, obteniendo de esta manera la refutación que buscabamos. 134 | 135 | $$\{ \{P,Q\},\{P,\lnot Q\},\{\lnot P, Q\},\{\lnot P, \lnot Q\}, \{P\}, \{\lnot P\}, \red{\Box} \}$$ 136 | -------------------------------------------------------------------------------- /apuntes/secciones/resolucion_sld.tex: -------------------------------------------------------------------------------- 1 | 2 | \section{Resolución SLD} 3 | Si bien los métodos que propusimos hasta ahora son completos, hallar refutaciones es un proceso muy car en el caso general, el espacio de búsqueda que producen puede ser enorme y tienen un alto grado de no-determinismo. Debemos agregar ciertas restricciones que nos permitan reducir este espacio sin que esto afecte a la completitud del método. 4 | 5 | \subsection{Resolución lineal} 6 | Una secuencia de pasos de resolución a partir de $S$ es \textbf{lineal} si es de la forma: 7 | 8 | \begin{center} 9 | \begin{forest} resolucion, 10 | [$C_p~{=}~\Box$ 11 | [$C_{p-1}$,edge label={node[midway,right] {$\blue{\sigma_p}$}} 12 | [$\dots$,edge label={node[midway,right] {$\blue{\sigma_{p-1}}$}} 13 | [$C_3$, 14 | [$C_2$,edge label={node[midway,right] {$\blue{\sigma_3}$}} 15 | [$C_1$, edge label={node[midway,right] {$\blue{\sigma_2}$}} 16 | [$C_0$, edge label={node[midway,right] {$\blue{\sigma_1}$}}] 17 | [$B_1$] 18 | ] 19 | [$B_2$] 20 | ] 21 | [$B_3$] 22 | ] 23 | ] 24 | [$B_{p-1}$] 25 | ] 26 | [$B_p$] 27 | ] 28 | \end{forest} 29 | \end{center} 30 | 31 | donde $C_0$ y cada $B_i$ es un elemento de $S$ o algún $C_j$ con $j < i$. 32 | 33 | Este tipo de resolución reduce el espacio de búsqueda considerablemente, sin embargo sigue siendo altamanente no-deterministico ya que no se se especificó ningún criterio de búsqueda ni selección de las cláusulas que debemos usar de este espacio. 34 | 35 | \subsection{Cláusulas de Horn} 36 | Podemos lograr una mayor eficiencia en el proceso de producir refutaciones si solo consideramos una \textbf{subclase} de fórmulas lo suficientemente expresivas. Es decir, que si bien existirán fórmulas que no podremos resolver con este método, las fórmulas que resolveremos tendrán el suficiente poder como para ser un método computacionalmente completo. 37 | 38 | El subconjunto de clásulas que vamos a usar son las cláusulas de Horne: 39 | 40 | Una cláusula $\forall x_1\dots\forall x_m.C$ tal que la disyunción de literales $C$ tiene \textbf{a lo sumo} un literal positivo. Y diremos que una cláusula de esta forma es una \textbf{cláusula de definición} cuando $C$ tiene \textbf{exactamente} un literal positivo. 41 | 42 | El método de resolución SLD, tendrá como entrada un conjunto de cláusulas de Horn $S = P\cup \{G\} $ donde $P$ es nuestro programa (conjunto de axiomas y reglas de entrada o base de conocimiento) y $G$ es nuestro goal. 43 | 44 | Una secuencia de pasos de \textbf{resolución SLD} para $S$ es una secuencia $$ de \textbf{cláusulas negativas} que satisfacen las siguientes dos condiciones: 45 | \begin{enumerate} 46 | \item $N_0$ es el goal $G$. 47 | \item para todo $N_i$ en la secuencia, $0 < i < p$, si $N_i$ es 48 | $$\{\lnot A_1,\dots, \lnot A_{k-1}, \lnot A_{k}, \lnot A_{k+1},\dots, \lnot A_n\}$$ 49 | entonces hay alguna \textbf{cláusula de definición} $C_i$ de la forma $\{A,\lnot B_1,\dots, \lnot B_m\}$ en $P$ tal que $A_k$ y $A$ son unificable con el MGU $\sigma$ y si : 50 | \begin{itemize} 51 | \item $m = 0$, entonces $N_{i+1}E$ es 52 | $$\{ \sigma(\{\lnot A_1,\dots, \lnot A_{k-1}, \lnot A_{k+1},\dots, \lnot A_n\}) \}$$ 53 | \item $m > 0$, entonces $N_{i+1}E$ es 54 | $$\{ \sigma(\{\lnot A_1,\dots, \lnot A_{k-1}, \lnot B_1,\dots, \lnot B_m, \lnot A_{k+1},\dots, \lnot A_n\}) \}$$ 55 | \end{itemize} 56 | \end{enumerate} 57 | 58 | Esto significa que cada paso de la secuencia es la resolución del pase anterior con una cláusula de Horne definida en nuestro programa que tiene un literal positivo $A$ que unifica con algún literal $A_k$ negado en dicho paso. Llamaremos \textbf{átomo seleccionado} al literal $A_k$. Y \textbf{sustitución respuesta} a la composición de las sustituciones. 59 | 60 | Este es el método que usa Prolog para extraer la salida del programa. Por ejemplo, si consideramom el siguiente programa: 61 | 62 | \begin{itemize} 63 | \item $C_1 = \{add(U,O,U)\}$ 64 | \item $C_1 = \{add(X,succ(Y),succ(Z), \lnot add(X,Y,Z)\}$ 65 | \end{itemize} 66 | 67 | Y definimos nuestro goal $G = \{\lnot add(succ(0),V,succ(succ(0))))\}$, entonces una resolución posible es la siguiente: 68 | 69 | \begin{center} 70 | \begin{forest} resolucion, 71 | [$\Box$ 72 | [$\{\lnot add(succ(0){,}~V{,}~succ(succ(0))\}$,edge label={node[midway,right] {$\sigma_2$}} 73 | [$\{\lnot add(succ(0){,}V{,}succ(succ(0))))\}$,edge label={node[midway,right] {$\sigma_1$}} 74 | ] 75 | [$C_2$] 76 | ] 77 | [$C_1$] 78 | ] 79 | \end{forest} 80 | \end{center} 81 | 82 | $\sigma_1 = \{ X\leftarrow succ(0),~Z\leftarrow succ(0),~ V\leftarrow succ(Y)\}$ 83 | 84 | $\sigma_2 = \{ U\leftarrow succ(0),~Y\leftarrow 0\}$ 85 | 86 | Y la sustitución resultado es: $$\{ X\leftarrow succ(0),~Z\leftarrow succ(0),~ V\leftarrow succ(0),U\leftarrow succ(0),~Y\leftarrow 0\}$$ 87 | 88 | \subsubsection{Corrección y completitud} 89 | 90 | \paragraph{Corrección} Si un conjunto de cláusulas de Horn tiene una refutación SLD, entonces es insatisfactible. 91 | 92 | \paragraph{Completitud} Dado un conjunto de cláusulas de Horn $P\cup \{G\}$, si $P\cup \{G\}$ es insatisfactible, existe una refutación SLD cuya primera cláusula es $G$. 93 | 94 | \subsection{Resolución SLD en Prolog} 95 | El método SLD todavía deja sin determinar como realizar la búsqueda y la selección de las cláusulas de nuestro programa para aplicar en la resolución. Para solucionar esto, se usan \textbf{estrategias} que determinan la forma de los árboles de búsqueda o \textbf{árbol SLD} de nuestra resolución. 96 | 97 | 98 | Esto quiere decir que cuando diseñamos un programa debemos tener en cuenta la estrategia que estamos usando para determinar el orden de las cláusulas que estamos definiendo. Hay que tratar de que el método consiga, primero, las soluciones de las ramas ``mas interesante'' y luego explore el resto del árbol. 99 | 100 | Podría llegar a pasarnos que, debido a una mala elección de este orden (para la estrategia elegida), el método no encuentre una refutación para una expresión que es insatisfactible. 101 | 102 | Prolog, en particular, selecciona las cláusulas del programa de arriba hacia abajo, es decir, en el orden en que fueron introducidas y el átomo seleccionado en cada paso es el átomo de más a la izquierda de la fórmula. Además, como puede haber varias resoluciones SLD, Prolog realiza backtracking sobre las reglas usadas para generar todas las soluciones posibles. 103 | Si consideramos el siguiente programa: 104 | 105 | \begin{enumerate} 106 | \item $\{ p(X,Z),~\lnot q(X,Y), \lnot p(Y,Z) \}$ 107 | \item $\{ p(X,X)\}$ 108 | \item $\{q(a,b)\}$ 109 | \end{enumerate} 110 | 111 | Y nuestro goal es $\{\lnot p(X,b)\}$, entonces, Prolog, realizaría el siguiente árobl SLD: 112 | 113 | \includegraphics[scale=0.4]{imagenes/arbol_sld_prolog.png} 114 | 115 | Otra posible estrategia de selección sería, por ejemplo, elegir resolver la cláusula más a la derecha, en cuyo caso el ejemplo que dimos dejaría de funcionar ya que la primer rama del árbol sería infinita y no encontrariamos nunca una refutación. 116 | 117 | Y si decidiesemos seleccionar las cláusulas de abajo hacia arriba, entonces obtendriamos el árbol mostrado reflejado. 118 | 119 | Hay que tener en cuenta que elegimos el ejemplo para que funcionase bien con la estrategia que sigue Prolog, sin embargo, hay ejemplos en lo que esta estrategia cae en el mismo caso que en la primer estrategia alternativa mencionada. 120 | 121 | \subsubsection{Implementación y otras cosas sobre Prolog} 122 | La estrategia usada por Prolog recorre el árbol SLD en \textbf{profundidad} (depth-first search). Las ventajas de esto es que puede ser implmentado de manera muy eficiente usando una \textbf{pila} para representar los átomos del goal. 123 | La idea es hacer un \textbf{push} del resolvente del átomo del tope de la pila con la cláusula de definición y hacer un \textbf{pop} cuando el átomo del top de la pila no unifica con ninguna cláusula de definición más. 124 | 125 | \subsubsection*{Cut} 126 | Es una notación que nos permite \textbf{podar} el árbol SLD. Es de carácter extra-lógico y nos permite \textbf{hacer más eficientes} algunas consultas. El uso correcto de esta notación no debería modificar el universo de posibles soluciones a una consulta. 127 | 128 | Cuando se selecciona un cut, tiene éxito \textbf{inmediatamente}. Si, debido a backtracking, se vuelve al mismo cut entonces se hace fallar el goal que le dio origen. 129 | 130 | \subsection*{Negación por falla} 131 | Se dice que un árbol SLD \textbf{falla finitamente} si es finito y no tiene ramas de éxito. 132 | 133 | Dado un programa P el \textbf{conjunto de falla finita} de $P$ es $$\{ B ~|~B~ \text{ es un átomo cerrado y existe un árbol SLD que falla finitamente con } B \text{ como raíz}\} $$ 134 | 135 | Esto significa que podemos inferir la insatisfactibilidad de una cláusula cerrada si la cantidad de chequeos que tenemos que hacer para probarlo es finita y si, además, tenemos un conjunto finito de símbolos sobre los que chequear. 136 | 137 | En Prolog, tenemos el predicado \textbf{not} que nos permite realizar este tipo de resolución, sin embargo debemos asegurarnos de que los predicados que le pasemos sean cerrados, ya que al no ser un predicado lógico, no se instancias variables en ningún momento. -------------------------------------------------------------------------------- /apuntes/secciones/subtipado.tex: -------------------------------------------------------------------------------- 1 | \section{Subtipado} 2 | Muchos lenguajes nos ofrecen la posibilidad de trabajar con subtipos. Esto significa que definen una relación entre sus tipos que, en ciertos casos, nos permite usar a un elemento de un tipo como si fuese un elemento de otro. Por ejemplo, si tenemos una función que toma dos $Float$ (reales) y nos devuelve su suma, a esa función podriamos pasarle un $Nat$ (natural) o un $Int$ (entero) y podríamos ejecutarla sin problema ya que estos tipos, en realidad, son subconjuntos de los reales. 3 | 4 | \paragraph{Principio de sustitutividad} 5 | Definimos la relación $\sigma <: \tau$, que indica que en todo contexto donde se espera una expresión de tipo $\tau$, podemos utilizar una de tipo $\sigma$ en su lugar \textbf{sin} que ello genere un error. Y además agregamos la regla de subtipado (\textbf{Subsumption}) T-Subs: 6 | $$\frac{\judgeType{\Gamma}{M}{\sigma}~\hspace*{5mm}~\sigma <:\tau}{\judgeType{\Gamma}{M}{\tau}}(\text{T-Subs})$$ 7 | 8 | Esta regla es la que nos dice que si tenemos una expresión de tipo $\sigma$ tal que $\sigma <: \tau$, entonces también podremos considerar a $M$ como una expresión de tipo $\tau$. 9 | \paragraph{El tipo máximo} $Top$: Contiene a todos los tipos del lenguaje y lo llamaremos \textbf{supertipo universal} porque todo tipo es subtipo de éste: 10 | $$\frac{}{\sigma <: Top}(S-Top)$$ 11 | 12 | \paragraph{Tipos con constructores invariantes:} Son tipos que no pueden ser remplazados por ningún otro. 13 | 14 | \paragraph{Tipos con constructores covariantes:} Sus subtipos se consiguen remplazando los tipos de los argumentos de sus constructores por uno de sus subtipos. 15 | 16 | \paragraph{Tipos con constructores contravariantes:} Sus subtipos se consiguen remplazando los tipos de los argumentos de sus constructores por un supertipo del argumento. 17 | 18 | 19 | \subsection{Reglas de subtipado} 20 | \subsubsection{Tipos básicos} 21 | \begin{align*} 22 | \frac{}{Nat <: Float}(\text{S-NatFloat}) \hspace*{5mm}\frac{}{Int <: Float}(\text{S-IntFloat}) \hspace*{5mm}\frac{}{Bool <: Nat}(\text{S-BoolNat}) 23 | \end{align*} 24 | 25 | 26 | \subsubsection{Subtipado del tipo función} 27 | Buscamos una función $g:\sigma\to\tau$ que pueda remplazar a otra función $f:\sigma'\to\tau'$ en cualquier contexto sin generar ningún error. 28 | \paragraph{Dominio:} $g$ debe estar definida para todos los elementos del dominio de $f$, osea $Dom(f)\subseteq Dom(g)$. Si pasara que existe un valor $x$ tal $f(x)$ está definida y $g(x)$ no lo está, cuando remplazemos a $f$, obtendríamos un error. Entonces, $\sigma' <: \sigma$. 29 | 30 | \paragraph{Imagen:} $g$ no debería poder devolver como resultado ningún valor que no esperamos que $f$ no devuelva ($Im(g)\subseteq Im(f)$). Si $g$ devolviese algo elemnto de un tipo que no estamos esperando cuando usamos $f$, podría ocasionar problemas. Luego $\tau <: \tau'$. 31 | 32 | \paragraph{Ejemplo:} Supongamos que tenemos la función $\text{esPar} :: Nat\to Nat$, cuando usemos esta función, el contexto en el que la usemos estará esperando conseguir un natural de su evaluación. Si la función $g$ devuelve algo que no sea un $Nat$, entonces obtendriamos un error. Sin embargo, si $g :: Nat\to Bool$, entonces podremos realizar el remplazo sin ningún problema porque $\{0,1\}$ es un subconjunto de los naturales. 33 | 34 | \paragraph{Regla de subtipado de funciones:} 35 | 36 | \vspace*{5mm} 37 | $$\frac{\sigma' <: \sigma\hspace*{5mm}\tau <: \tau'}{\sigma\to\tau <: \sigma'\to\tau'}(\text{S-Func})$$ 38 | 39 | \vspace*{5mm} 40 | El constructor de tipos función es \textbf{contravariante} en su primer argumento y \textbf{covariante} en el segundo. 41 | 42 | Un programa $P$, deberá \textbf{coercionar} (transformar) el argumento que le pasan a la función para que coincida con el tipo de la nueva función, ejecutarla y luego coercionar su resultado al tipo del resultado que espera $P$. 43 | 44 | \subsubsection{Reglas de subtipado de términos} 45 | Las reglas de tipado sin subtipos son dirigidas por sintaxis, por lo que es inmediato implementar un algoritmo de chequeo de tipos a partir de ellas. Con el agregado de la regla T-Subs, el chequeo también pasa a estar dirigido por la semántica de la relación $<:$ por lo que el algoritmo deja de ser tan directo. 46 | 47 | Un juicio de subtipado $\judgeTypeS{\Gamma}{M}{\sigma}$, nos dice que $\judgeType{\Gamma}{M}{\sigma}$ y que existe existe $\tau$ tal que $\judgeTypeS{\Gamma}{M}{\tau}$ con $\tau <: \sigma$. Entonces las nuevas reglas quedarían así: 48 | 49 | \begin{equation*} 50 | \begin{gathered} 51 | \frac{x:\sigma\in\Gamma}{\judgeTypeS{\Gamma}{x}{\sigma}}(\text{T-Var})\hspace*{2cm} 52 | \vspace*{5mm} \\ 53 | \frac {\judgeTypeS{\Gamma,x:\sigma}{M}{\tau}} 54 | {\judgeTypeS{\Gamma}{\lambdaAbs{x}{\sigma}{M}}{\sigma\to\tau}}(\text{T-Abs})\hspace*{2cm} 55 | \frac{\judgeTypeS{\Gamma}{M}{\sigma\to\tau}\hspace*{5mm}\judgeTypeS{\Gamma}{N}{\blue{\rho}}\hspace*{5mm}\blue{\rho <: \sigma}}{\judgeTypeS{\Gamma}{M~N}{\tau}}(\text{T-App}) 56 | \end{gathered} 57 | \end{equation*} 58 | 59 | La mayoría de las reglas de subtipado son similares a las reglas de tipo. La única regla que usa la relación $<:$ de manera explicita es T-App porque los términos de aplicación son los únicos que al ser evaluados remplazan expresiones y, efectivamente, esta regla es la que nos da el poder que estábamos buscando. 60 | 61 | 62 | \subsubsection{Relación de preorden} La relación de subtipado $<:$ define una relación de preorden, es decir es reflexiva y transitiva por lo que podriamos escribir las siguientes reglas: 63 | 64 | $$\frac{}{\sigma <: \sigma}(\text{S-Refl}) \hspace*{1cm}\frac{\sigma <:\tau\hspace*{5mm}\tau <: \rho}{\sigma <: \rho}(\text{S-Trans})$$ 65 | 66 | Sin embargo, esta forma de descrbir la relación no es dirigida por semántica y no está claro como hacer un algoritmo de chequeo de subtipos que use estas reglas. Por esta razón vamos a considerar los siguientes tres axiomas: 67 | 68 | \begin{align*} 69 | \frac{}{Nat <: Nat}(\text{S-NatNat}) \hspace*{5mm}\frac{}{Bool <: Bool}(\text{S-BoolBool}) \hspace*{5mm}\frac{}{Float <: Float}(\text{S-FloatFloat}) 70 | \end{align*} 71 | 72 | \vspace*{5mm} 73 | Y ya con eso alcanza para derivar la reflexibidad de cualquier tipo del lenguaje, en el lenguaje $\lambda$ básico. Si agregásemos un nuevo tipo escalar (sin parámetros), debemos declarar explícitamente que ese tipo es subtipo de si mismo, sino el preorden se rompe. 74 | 75 | La transitividad se puede demostrar aplicando varios pasos de subtipado, por lo que directamente no es necesaria. 76 | 77 | \subsubsection{Algoritmo de chequeo de tipos} 78 | Como todas las reglas del sistema de subtipado fueron definidas de manera tal que son dirigidas por la sintaxis, podemos definir el algoritmos $subtype(S,T)$ que nos indica si $S$ es subtipo de $T$. Al algoritmo mostrado le faltan los axiomas de $Nat$, $Bool$ y $Float$ que son triviales (hay que poner cada una de esas comparaciones una por una): 79 | 80 | \includegraphics[scale=0.4]{imagenes/algoritmo_subtipado.png} 81 | 82 | \subsection{Subtipado de referencias} 83 | Queremos encontrar el tipo $Ref~\tau$ que sea subtipo de $Ref~\sigma$. 84 | \begin{itemize} 85 | \item Supongamos que $\tau <: \sigma$, si intentamos subtipar una referencia $M:Ref~\sigma$ con $Ref~\tau$, entonces cuando realicemos una asignación podremos usar un valor de tipo $\tau$ y no tendremos error. Sin embargo, cuando derreferenciemos $M$, estaremos esperando algo de tipo $\sigma$ pero como $\tau$ es más general puede tener valores que no son de ese tipo y podriamos obtener un error. 86 | 87 | \paragraph{Ejemplo:}\begin{align*} 88 | &\lambdaLetI{r}{\text{ref}~3}{r := 2.1}; \\ 89 | &!r 90 | \end{align*} 91 | Como definimos $r$ como una referencia de enteros en el let, cuando derreferenciemos $r$ esperamos conseguir un entero, sin embargo la regla covariante, hace que con la asignación podamos asignar a $r$ un $Float$. 92 | 93 | \item Si $\sigma <: \tau$ y $M: Ref~\sigma$, entonces podemos guardar en $M$ un elemento de tipo $\sigma$. Cuando querramos derreferenciar $M$, como $Ref~\sigma$ es subtipo de $Ref~\tau$, podriamos usar la derreferencia del segundo tipo. El problema vuelve a ser el mismo, el contexto va a estar esperando un valor de tipo $\tau$ y $\sigma$ es más general por lo que el valor almacenado en $M$ puede no ser de este tipo, lo que llevaría a un error. 94 | 95 | \paragraph{Ejemplo:}\begin{align} 96 | \lambdaLetI{r}{\text{ref}~2.1}{!r} 97 | \end{align} 98 | 99 | Definimos a $r$ como una referencia de $Float$. Como $r$ es subtipable a $Ref~Int$, podemos usar la derreferenciación de enteros para derreferenciarla, lo que provocaría el error en el programa. 100 | 101 | \end{itemize} 102 | 103 | Concluimos que la regla de subtipado de referencias no es ni contravariante ni covariente, es variante. La única ``sustitución" que podemos hacer es cuando $\sigma$ y $\tau$ son el mismo tipo. 104 | 105 | $$\frac{\sigma <: \tau\hspace*{5mm} \tau <: \sigma}{Ref~\tau <: Ref~\sigma}$$ 106 | 107 | \subsubsection{Refinando el tipo \texorpdfstring{\textit{Ref}}{Ref}} 108 | Extendemos el lenguaje, con los siguiente tipos $Source~\sigma$ y $Sink~\sigma$ que representan las referencias de lectura y las de escritura, respectivamente. 109 | 110 | \paragraph{Reglas de tipado} 111 | 112 | \begin{align*} 113 | \frac{\judgeType{\Gamma|\Sigma}{M}{Source~\sigma}}{\judgeType{\Gamma|\Sigma}{!M}{\sigma}}(\text{T-DeRefSource}) 114 | \end{align*} 115 | 116 | \begin{align*} 117 | \frac{\judgeType{\Gamma|\Sigma}{M}{Sink~\sigma}\hspace*{5mm} \judgeType{\Gamma|\Sigma}{N}{\sigma}}{\judgeType{\Gamma|\Sigma}{M := N}{Unit}}(\text{T-AssignSink}) 118 | \end{align*} 119 | 120 | \paragraph{Reglas de subtipado} 121 | \begin{align*} 122 | \frac{\sigma <: \tau}{Source~\sigma <: Source~\tau}(\text{S-Source})\hspace*{1cm}\frac{\tau <: \sigma}{Sink~\sigma <: Sink~\tau}(\text{S-Sink}) 123 | \end{align*} 124 | 125 | \begin{align*} 126 | \frac{}{Ref~\tau <: Source~\tau}(\text{S-RefSource})\hspace*{1cm}\frac{}{Ref~\tau <: Sink~\tau}(\text{S-RefSink}) 127 | \end{align*} 128 | La regla S-Source es covariante.Si esperamos leer de una referencia de tipo $\tau$, entonces podemos esperar una referencia de un tipo más especifico que $\tau$. 129 | 130 | La regla S-Sink es contravariante. Cuando querramos guardar un valor de tipo $\tau$, podremos guardarlo en una referencia de este tipo o en una de un tipo más general. 131 | 132 | Además, $Source~\tau$ y $Sink~\tau$ son menos generales que $Ref~\tau$ ya que siempre podremos remplazar referencias de lecturas o de escritura por referencias de lectura y escritura. -------------------------------------------------------------------------------- /soluciones_haskell_js_prolog/practica7.pl: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Ejercicio N 1 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | 5 | padre(juan, carlos). %1 6 | padre(juan, luis). %2 7 | padre(carlos, daniel). %3 8 | padre(carlos, diego). %4 9 | padre(luis, pablo). %5 10 | padre(luis, manuel). %6 11 | padre(luis, ramiro). %7 12 | 13 | abuelo(X,Y) :- %8 14 | padre(X,Z), 15 | padre(Z,Y). 16 | 17 | 18 | %% II. 19 | 20 | hijo(X, Y) :- %9 21 | padre(Y, X). 22 | 23 | hermano(X, Y) :- %10 24 | padre(Z, X), 25 | padre(Z, Y), 26 | X \= Y. 27 | 28 | 29 | descendiente(X, Y) :- %11 30 | hijo(X,Y). 31 | descendiente(X,Y) :- %12 32 | hijo(X, Z), 33 | descendiente(Z, Y). 34 | 35 | 36 | %% IV) 37 | ancestro(X, X). %13 38 | ancestro(X, Y) :- %14 39 | padre(X, Z), 40 | ancestro(Z, Y). 41 | 42 | 43 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 44 | % Ejercicio N 2 45 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 46 | vecino(X, Y, [ _ | Ls ]) :- vecino(X, Y, Ls). %2 47 | vecino(X, Y, [ X | [ Y | _ ] ] ). %1 48 | 49 | 50 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 51 | % Ejercicio N 3 52 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 53 | natural(0). %1 54 | natural(suc(X)) :- natural(X). %2 55 | 56 | 57 | menorOIgual(X,X) :- natural(X). %4 58 | menorOIgual(X, suc(Y)) :- menorOIgual(X, Y). %3 59 | 60 | 61 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 62 | % Ejercicio N 4 63 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 64 | 65 | %concatenar(?Lista1, ?Lista2, ?Lista3) 66 | concatenar([], Lista2, Lista2). 67 | concatenar([X | T1], Lista2, [X| T3]) :- 68 | concatenar(T1, Lista2, T3). 69 | 70 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 71 | % Ejercicio N 5 72 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 73 | 74 | % I. 75 | %last(?L, ?U) 76 | last([ X ], X ). 77 | last([ _ | T ], Y) :- last(T,Y). 78 | 79 | % II. 80 | 81 | %reverse(+L, -L1) 82 | tienenLaMismaLongitud(L1, L2) :- 83 | length(L1, N ), 84 | length(L2, N ). 85 | 86 | reverse([],[]). 87 | reverse( [ X | T ], R) :- 88 | tienenLaMismaLongitud([X | T], R), 89 | reverse(T, RT ), 90 | append(RT, [ X ], R). 91 | 92 | %III. 93 | %maxLista(+L, -M) 94 | maxLista([X], X). 95 | maxLista([X | T], X) :- 96 | maxLista(T, Y), 97 | X >= Y. 98 | maxLista([X | T], Y) :- 99 | maxLista(T, Y), 100 | Y >= X. 101 | 102 | %minLista(+L, -M) 103 | minLista([X], X). 104 | minLista([X | T], X) :- 105 | minLista(T, Y), 106 | Y >= X. 107 | minLista([X | T], Y) :- 108 | minLista(T, Y), 109 | X >= Y. 110 | 111 | % IV. 112 | %prefijo(?P, +L) 113 | prefijo([], _). 114 | prefijo([ X | T1 ], [ X | T2 ]) :- 115 | prefijo(T1, T2). 116 | 117 | % V. 118 | %sufijo(?S, +L) 119 | sufijo(S, L ) :- 120 | prefijo(P, L), 121 | append(P, S, L). 122 | 123 | % VI. 124 | %sublista(?S, +L) 125 | sublista([], _). 126 | sublista(XS, L) :- 127 | prefijo(P, L), 128 | sufijo(S, L), 129 | append(P, XS, P1), 130 | append(P1, S, L), 131 | length(XS, N), 132 | N >= 1. 133 | 134 | 135 | % VII. 136 | %pertenece(?X, +L) 137 | pertenece(X, [ X | _]). 138 | pertenece(X, [ _ | XS ]) :- 139 | pertenece(X, XS). 140 | 141 | 142 | 143 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 144 | % Ejercicio N 6 145 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 146 | 147 | %aplanar(+XS, -YS) 148 | aplanar([],[]). 149 | aplanar([ [] | T ], Res) :- 150 | aplanar(T, Res). 151 | aplanar([ [X | T1 ] | T ], Res) :- 152 | aplanar([ X | T1 ], Y), 153 | aplanar(T, RecT), 154 | append(Y, RecT, Res). 155 | aplanar([ X | T ], [X | Res]) :- 156 | not(is_list(X)), 157 | aplanar(T, Res). 158 | 159 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 160 | % Ejercicio N 7 161 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 162 | 163 | %palindromo(+L, -L1) 164 | palindromo(L, L1) :- 165 | reverse(L, A), 166 | append(L,A,L1). 167 | 168 | %doble(+L, -L1) 169 | doble([], []). 170 | doble([ X | T], [X, X | Rec ]) :- 171 | doble(T, Rec). 172 | 173 | %iesimo(?I, +L, -X) 174 | iesimoAux(1, [X | _], X). 175 | iesimoAux(I, [_ | T], Y) :- 176 | I1 is I - 1, 177 | iesimo(I1, T, Y). 178 | 179 | iesimo(I, L, X) :- 180 | length(L, N), 181 | between(1,N, I), 182 | iesimoAux(I, L, X). 183 | 184 | 185 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 186 | % Ejercicio N 8 187 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 188 | desde(X,X). 189 | desde(X,Y) :- N is X+1, desde(N,Y). 190 | 191 | %desde2(+X,?Y) 192 | desde2(X, Y) :- 193 | nonvar(Y), 194 | Y >= X. 195 | desde2(X,Y) :- 196 | var(Y), 197 | desde(X,Y). 198 | 199 | 200 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 201 | % Ejercicio N 9 202 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 203 | 204 | % I. 205 | 206 | %interseccionAux(+L1, +L2, +L3, -L4) 207 | interseccionAux([], _, _, []). 208 | interseccionAux([ X | T ], L2, Usados, Resultado) :- 209 | not(member(X, L2)), 210 | interseccionAux(T, L2, Usados, Resultado). 211 | interseccionAux([ X | T ], L2, Usados, [ X | L4 ]) :- 212 | member(X, L2), 213 | not(member(X, Usados)), 214 | interseccionAux(T, L2, [ X | Usados], L4). 215 | interseccionAux([ X | T ], L2, Usados, L4 ) :- 216 | member(X, Usados), 217 | interseccionAux(T, L2, Usados, L4). 218 | 219 | %intersección(+L1, +L2, -L3) 220 | interseccion(L1, L2, L3) :- 221 | interseccionAux(L1, L2, [], L3). 222 | 223 | %II. 224 | %split(+N,+L, -L1, -L2) -- N y L deben estar definidos 225 | 226 | sufijoDeLongitud(L, N, S) :- 227 | sufijo(S, L), 228 | length(S, N). 229 | 230 | prefijoDeLongitud(L, N, S) :- 231 | prefijo(S, L), 232 | length(S, N). 233 | 234 | split(N, L, L1, L2) :- 235 | length(L, M), 236 | N1 is M - N, 237 | prefijoDeLongitud(L, N, L1), 238 | sufijoDeLongitud(L, N1, L2). 239 | 240 | % III. 241 | %borrar(+ListaOriginal, +X, -ListaSinXs) 242 | borrar([], _, []). 243 | borrar([X | T], X, ListaSinXs) :- 244 | borrar(T, X, ListaSinXs). 245 | borrar([ Y | T], X, [ Y | Rec ]) :- 246 | X \= Y, 247 | borrar(T, X, Rec). 248 | 249 | % IV. 250 | %sacarDuplicados(+L1, -L2) 251 | sacarDuplicados([], []). 252 | sacarDuplicados([ X | T], [ X | Rec ]) :- 253 | borrar(T, X, T1), 254 | sacarDuplicados(T1, Rec). 255 | 256 | %V. 257 | %concatenarTodas( +LL, -L) 258 | concatenarTodas([], []). 259 | concatenarTodas([ X | T], Res) :- 260 | concatenarTodas(T, Rec), 261 | concatenar(X, Rec, Res). 262 | 263 | %todosSusMiembrosSonSublitas(+LListas, +L) 264 | todosSusMiembrosSonSublitas([], _). 265 | todosSusMiembrosSonSublitas([ X | XS], L) :- 266 | sublista(X, L), 267 | todosSusMiembrosSonSublitas(XS, L). 268 | %reparto(+L, +N, -LListas) 269 | reparto(L, N, LListas) :- 270 | length(LListas, N), 271 | todosSusMiembrosSonSublitas(LListas, L), 272 | concatenarTodas(LListas, L). 273 | 274 | %VI. 275 | %repartoSinVacias(+L, -LListas) 276 | repartoSinVacias(L, LListas) :- 277 | length(L, N), 278 | between(1, N, X), 279 | reparto(L, X, LListas), 280 | not(member([], LListas)). 281 | 282 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 283 | % Ejercicio N 10 284 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 285 | 286 | %intercalar(?L1, ?L2, ?L3) -- Funciona para todas las combinaciones posibles. 287 | intercalar([], [], []). 288 | intercalar([], L, L) :- 289 | length(L, N), 290 | N >= 1. 291 | intercalar(L, [], L) :- 292 | length(L, N), 293 | N >= 1. 294 | intercalar([ X | T1], [ Y | T2 ], [ X, Y | T3 ] ) :- 295 | intercalar(T1, T2, T3). 296 | 297 | 298 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 299 | % Ejercicio N 11 300 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 301 | 302 | %arbolEjemplo 303 | arbolEjemplo(bin(bin(nil,1,nil),2,bin(bin(nil,10,nil),20,bin(nil,30,nil)))). 304 | 305 | %vacio(?A) 306 | vacio(nil). 307 | 308 | %raiz(?A, ?R) 309 | raiz(bin(_,X,_), X). 310 | 311 | %altura(+A, -H) 312 | altura(nil, 0). 313 | altura(bin(I, _, D), H) :- 314 | altura(I, HI), 315 | altura(D, HD), 316 | H is max(HI, HD) + 1. 317 | 318 | %cantidadDeNodos(+A, -N) 319 | cantidadDeNodos(nil, 0). 320 | cantidadDeNodos(bin(I, _, D), N) :- 321 | cantidadDeNodos(I, NI), 322 | cantidadDeNodos(D, ND), 323 | N is NI + ND + 1. 324 | 325 | 326 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 327 | % Ejercicio N 12 328 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 329 | 330 | %inorder(+AB, -Lista) 331 | inorder(nil, []). 332 | inorder(bin(I, X, D), Inorder) :- 333 | inorder(I, LI), 334 | inorder(D, LD), 335 | append(LI, [X | LD], Inorder). 336 | 337 | %arbolConInorder(-L, +AB) 338 | arbolConInorder([], nil). 339 | arbolConInorder(XS, bin(AI, X, AD)) :- 340 | reparto(XS, 2, [LI, [X | LD]]), 341 | arbolConInorder(LI, AI), 342 | arbolConInorder(LD, AD). 343 | 344 | %abb(+T) 345 | aBB(nil). 346 | aBB(bin(I, _, D)) :- 347 | aBB(I), 348 | aBB(D). 349 | 350 | %aBBInsertar(+X, +T1, -T2) 351 | aBBInsertar(X, nil, bin(nil, X, nil)). 352 | aBBInsertar(X, bin(AI, Y, AD), bin(AIM, Y, AD)) :- 353 | X =< Y, 354 | aBBInsertar(X, AI, AIM). 355 | aBBInsertar(X, bin(AI, Y, AD), bin(AI, Y, ADM)) :- 356 | X >= Y, 357 | aBBInsertar(X, AD, ADM). 358 | 359 | 360 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 361 | % Ejercicio N 13 362 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 363 | 364 | %coprimos(-X,-Y) 365 | coprimos(X,Y) :- 366 | desde(2, X), 367 | between(2, X, Y), 368 | 1 is gcd(X,Y). 369 | 370 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 371 | % Ejercicio N 14 372 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 373 | listasQueSuman([],0,0). 374 | listasQueSuman([X|XS],S,N):- 375 | between(0,S,X), 376 | N2 is N-1, 377 | length(XS,N2), 378 | S2 is S-X, 379 | listasQueSuman(XS,S2,N2). 380 | 381 | cuadradoSemiLatinoAux(_,0,[],_). 382 | cuadradoSemiLatinoAux(M,N,[X|XS],S):- 383 | N2 is N-1, 384 | listasQueSuman(X,S,M), 385 | cuadradoSemiLatinoAux(M,N2,XS,S). 386 | 387 | cuadradoSemiLatino(N,XS):- 388 | length(XS,N), 389 | desde(0,S), 390 | cuadradoSemiLatinoAux(N,N,XS,S). 391 | 392 | 393 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 394 | % Ejercicio N 15 395 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 396 | %ladoValido(+A, +B, +C) 397 | ladoValido(A,B,C) :- 398 | S is B+C, 399 | A < S, 400 | D is abs(B-C), 401 | A > D. 402 | 403 | %esTriangulo(+T) 404 | esTriangulo(tri(A,B,C)) :- 405 | ladoValido(A,B,C), 406 | ladoValido(B,C,A), 407 | ladoValido(C,A,B). 408 | 409 | %perı́metro(?T,?P) 410 | perimetro(tri(A,B,C), P) :- 411 | desde2(3,P), 412 | M is P-2, 413 | between(1,M,A), 414 | N is P - A -1, 415 | between(1, N, B), 416 | C is P - A - B, 417 | esTriangulo(tri(A,B,C)). 418 | 419 | 420 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 421 | % Ejercicio N 16 422 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 423 | 424 | %diferenciaSimétrica(Lista1, +Lista2, -Lista3) 425 | diferenciaSimetrica([], L2, L2). 426 | diferenciaSimetrica([ X | L1], L2, [ X | XS]) :- 427 | not(member(X, L2)), 428 | diferenciaSimetrica(L1, L2, XS). 429 | diferenciaSimetrica([ X | L1], L2, XS) :- 430 | member(X, L2), 431 | borrar(L2, X, L2SinX), 432 | diferenciaSimetrica(L1, L2SinX, XS). 433 | 434 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 435 | % Ejercicio N 18 436 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 437 | %sumList 438 | sumList([], 0). 439 | sumList([X | XS], N) :- 440 | sumList(XS, N1), 441 | N is N1 + X. 442 | 443 | %diff 444 | diff(L1, L2, DL) :- 445 | sumList(L1, N1), 446 | sumList(L2, N2), 447 | DL is abs(N1-N2). 448 | 449 | %corteMásParejo(+L,-L1,-L2) 450 | corteMasParejo(L, L1, L2) :- 451 | append(L1, L2, L), 452 | diff(L1,L2,DL), 453 | not((append(M1,M2,L), 454 | diff(M1,M2,DM), 455 | DM < DL 456 | )). 457 | -------------------------------------------------------------------------------- /apuntes/secciones/prototipado.tex: -------------------------------------------------------------------------------- 1 | 2 | \section{Prototipado} 3 | Lo lenguajes basados en prototipado de objetos se caracterizan por la ausencia de clases. Proveen constructores para la creación de objetos particulares y la herramientas necesarias para crear procedimientos que generen objetos. 4 | 5 | En este tipo de paradigma, creamos objetos concretos (llamados \textbf{prototipos}) que se interpretan como representantes canónicos de cierto conjunto de objetos y, a partir de ellos, generamos otras intancias (\textbf{clones}) que pueden ser modificadas sin afectar al prototipo. 6 | 7 | Cuando clonamos realizamos lo que se llama una \textbf{shallow copy} del objeto clonado, es decir copiamos cada atributo, con su método, del objeto original en el nuevo. Esto significa que cada atributo tiene exactamente la misma definición en ambos objetos. 8 | 9 | Una consecuencia de esto es que si un atributo es una referencia a un objeto $A$, entonces en el nuevo objeto será una referencia a $A$ y cualquier modificación que le hagamos se verá reflejada en ambos objetos. 10 | 11 | \subsection{Cálculo de objetos no tipado \texorpdfstring{($\varsigma$}{(Sigma} cálculo)} 12 | Usaremos un lenguaje cuya única estructura computacional son los \textbf{Objetos}. Estos objetos son una colección de atributos nombrados (\textbf{registros}) que están asociados a métodos con una única variable ligada (que representa a \texttt{self}/\texttt{this}) y un cuerpo que produce un resultado. 13 | 14 | Todos los objetos proveen dos operaciones: 15 | 16 | \paragraph{Envío de mensajes:} Que nos permite invocar un método para que el objeto ejecute. 17 | 18 | \paragraph{Redefinición de un método:} Que nos permite reemplazar el cuerpo de un atributo por otro. 19 | 20 | \subsubsection{Sintaxis} 21 | \begin{tabular}{lllll} 22 | $a,b$ &$::=$& &$x$ & Variables \\ 23 | & & $|$ &$[\OOAtributo{l_i}{x_i}{b_i}^{i\in1..n}]$ & Objetos\\ 24 | & & $|$ &$a.l$ & Selección/ Envío de mensajes \\ 25 | & & $|$ &$\OORedefinicion{a.l}{x}{b}$ & Redefinición de un método. 26 | \end{tabular} 27 | 28 | \vspace*{5mm} 29 | El objeto $[~]$ es el objeto vacío y no proporciona ningún método. 30 | 31 | En este lenguajes, como todos los átributos son métodos, simulamos los colaboradores internos de un objeto con métodos que no utilizan el parámetro \texttt{self}. Por ejemplo: 32 | 33 | $$o \equalDef [\OOAtributo{l_1}{x_1}{[~]},~ 34 | \OOAtributo{l_2}{x_2}{x_2.l_1}]$$ 35 | 36 | $o.l_1$ retorna un objeto vacío. Y $o.l_2$ envia el mensaje $l_1$ a \texttt{self} (representado por el parámetro $x_2$). 37 | 38 | \paragraph{Notación} Cuando un objeto tenga un atributo de la forma $\OOAtributo{l}{x}{b}$ y $x$ no se usa en $b$ podemos escribir $l = b$ y a la reasignación $\OORedefinicion{o.l}{x}{b}$ como $o.l := b$. 39 | 40 | \paragraph{Variables libres} 41 | $\varsigma$ es un ligador de variables, cuando lo usamos en una expresión de la forma $\varsigma(x)b$ siempre liga la variable $x$ que se le pasa como párametro a \texttt{self}. 42 | 43 | De manera análoga a $FV$ del cálculo $\lambda$ definimos fv para objetos y diremos que un término $a$ es \textbf{cerrado} si fv($a$) = $\emptyset$: 44 | 45 | \begin{center} 46 | \begin{tabular}{ll} 47 | $\text{fv}(\varsigma(x)b)$ &$= \text{fv}(b)\backslash \{x\} $\\ 48 | $\text{fv}(x)$ &$= \{x\} $\\ 49 | $\text{fv}([\OOAtributo{l_i}{x_i}{b_i}^{i\in 1..n}])$ &$= \bigcup^{1\in 1..n} \text{fv}(\varsigma(x)b)$\\ 50 | $\text{fv}(a.l)$ &$= \text{fv}(a) $\\ 51 | $\text{fv}(\OORedefinicion{a.l}{x}{b})$ &$= \text{fv}(a.l)\cup \text{fv}(\varsigma(x)b) $\\ 52 | \end{tabular} 53 | \end{center} 54 | \paragraph{Sustitución} La función de sustitución de variables libres para objetos está definida de la siguiente forma: 55 | 56 | \begin{center} 57 | \begin{tabular}{lll} 58 | $x\{x \leftarrow c\}$ &$= c$ & \\ 59 | $y\{x \leftarrow c\}$ &$= y$ & si $x\neq y$\\ 60 | $([\OOAtributo{l_i}{x_i}{b_i}^{i\in 1..n}])\{x \leftarrow c\}$ &$= [l_i = (\varsigma(x_i)b_i)\{x \leftarrow c\}^{i\in 1..n}]$ & \\ 61 | $(a.l)\{x \leftarrow c\}$ &$= (a\{x \leftarrow c\}).l $ & \\ 62 | $(\OORedefinicion{a.l}{x}{b})\{x \leftarrow c\}$ &$= (a\{x \leftarrow c\}).l \leftleftharpoons (\varsigma(x)b)\{x \leftarrow c\} $ & \\ 63 | $(\varsigma(y)b)\{x \leftarrow c\}$ &$= (\varsigma(y')(b\{y \leftarrow y'\}\{x \leftarrow c\})) $ & si $y'\notin$fv$(\varsigma(y)b)\cup$fv$(c)\cup\{x\}$ \\ 64 | \end{tabular} 65 | \end{center} 66 | 67 | Notemos que en el último caso, remplazamos $y$ por $y'$ por si $y = x$ asegurandonos, de esta manera, que no cambiamos el significado de la expresión. 68 | 69 | \paragraph{$\alpha$-conversión} En objetos decimos que dos objetos ($o_1 \equiv o_2$) son equivalentes si saben responder a los mismo mensajes y si los métodos asociados a cada uno de ellos son equivalentes en ambos objetos. Y dos métodos $\varsigma(x)b$ y $\varsigma(y)b_y$ son equivalente si $b_y\{y\leftarrow x\}\longrightarrow b$, es decir si la única diferencia entre ambos métodos es el nombre de las variables. 70 | 71 | 72 | \begin{align*} 73 | o_1 \equalDef [l_1 = [~],~\OOAtributo{l_2}{x_2}{x_2.l_1}] \\ 74 | o_2 \equalDef [\OOAtributo{l_2}{x_3}{x_3.l_1},~l_1 = [~]] 75 | \end{align*} 76 | 77 | son equivalentes porque ambos objetos tiene los atributos $l_1$ y $l_2$ y $\varsigma(x_2) x_2.l_1 =_\alpha \varsigma(x_3) x_3.l_1$. 78 | 79 | 80 | \subsubsection{Semántica operacional} 81 | Todos los objetos son considerados valores. 82 | $$V~::=~[\OOAtributo{l_i}{x_i}{b_i}^{1\in 1..n}]$$ 83 | 84 | A diferencía del cálculo $\lambda$, usaremos el método de reducción \textbf{big-step} para evaluar expresiones. Este método nos permite saber el valor que representa la expresión en un solo paso. 85 | 86 | $$\frac{}{v\longrightarrow v}[\text{Obj}]$$ 87 | \vspace*{5mm} 88 | $$\frac{a\longrightarrow v'\hspace*{5mm} v'\equiv [\OOAtributo{l_i}{x_i}{b_i}^{i\in 1..n}]\hspace*{5mm} b_j\{x_j\leftarrow v'\}\longrightarrow v\hspace*{5mm} j\in1..n}{a.l_j\longrightarrow v}[\text{Sel}]$$ 89 | 90 | \vspace*{5mm} 91 | $$\frac{a\longrightarrow [\OOAtributo{l_i}{x_i}{b_i}^{i\in 1..n}]\hspace*{5mm} j\in1..n}{\OORedefinicion{a.l_j}{x}{b}\longrightarrow [\OOAtributo{l_j}{x}{b},~\OOAtributo{l_i}{x_i}{b_i}^{i\in 1..n-\{j\}}]}[\text{Upd}]$$ 92 | 93 | 94 | La regla Obj nos dice que los objetos no reducen (o reducen a si mismos). 95 | 96 | Sel nos indica que el resultado de enviar un mensaje es el valor que obtenemos al remplazar el párametro del método asociado por el mismo objeto (esto es la ligación a \texttt{self}). 97 | 98 | Upd es el comportamiento de la redifinición, que devuelve un objeto con los mismos atributos que $a$ pero remplazando el $j-$ésimo atributo por la nueva definición. 99 | 100 | 101 | \paragraph{Ejemplo de reducción} 102 | 103 | \begin{center} 104 | \begin{scprooftree} 105 | \def\extraVskip{5pt} 106 | \AxiomC{$\OOReduccion{o}{o}$} 107 | 108 | \AxiomC{$\OOReduccion{o}{o}$} 109 | 110 | \AxiomC{} 111 | \RightLabel{[Obj]} 112 | \UnaryInfC{$\OOReduccion{[~]\{x\leftarrow o\}}{[~]}$} 113 | \RightLabel{[Sel]} 114 | \BinaryInfC{$\OOReduccion{(x.a)\{x\leftarrow o\}}{[~]}$} 115 | 116 | \RightLabel{[Sel]} 117 | \BinaryInfC{$\OOReduccion{[a=[~],~\OOAtributo{b}{x}{x.a}].b}{[~]}$} 118 | \end{scprooftree} 119 | \end{center} 120 | 121 | \paragraph{Indefinición} Similar al cálculo $\lambda$, podemos definir expresiones que se indefinen pero, en este caso, no es necesario que introduzcamos ninguna estructura nueva. Por ejemplos, si intentamos evaluar la expresión $[\OOAtributo{a}{x}{x.a}].a$ nos daremos cuenta de que su reducción es infinita. 122 | 123 | \paragraph{Codificación de funciones (Cálculo $\lambda$)} 124 | Modelamos las expresiones del cálculo $\lambda$ como objetos con un atributo $val$ que nos indica su valor, las funciones, además tiene el atributo $arg$ que representa al argumento de la función. El argumento de una función permanecerá indefinido hasta que aparezca en una aplicación. 125 | \begin{align*} 126 | \OORep{x} &\equalDef x\\ 127 | \OORep{M~N} &\equalDef \OORep{M}.arg :=~\OORep{N}\\ 128 | \OORep{\lambdaAbsI{x}{M}} &\equalDef 129 | [\OOAtributo{val}{y}{\OORep{M}\{x\leftarrow y.arg\}},~\OOAtributo{arg}{y}{y.arg}]\\ 130 | \end{align*} 131 | 132 | Cuando querramos representar un método que espera parámetros, usaremos la definición de función para escribirlo: $\varsigma(x)\OORep {\lambdaAbsI{y}{M}}$.Podemos hacer abuso de notacion y escribir $\lambda(y)M$ en vez de $\varsigma(x)\OORep {\lambdaAbsI{y}{M}}$ y $M(N)$, en vez de $\OORep{M~N}$. 133 | 134 | \subsubsection{Traits} 135 | Un trait es una colección de métodos que parametrizan cierto comportamientos. Estos objetos no especifican variables de estado ni acceden a su estado. 136 | 137 | El trait y sus métodos por si solo no son utilizables, ya que el trait no provee los estados necesarios para evaluarlos correctamente. Solo lo usaremos para definir métodos que pueden ser evaluados por varios objetos con el objetivo de no tener que repetir siempre las mismas definiciones. 138 | 139 | Los vamos a representar como una colección de \textbf{pre-metodos} (que no usan el parámetro \text{self}). Por lo que un trait tendrá la siguiente forma: 140 | $$\texttt{t} = [l_i = \lambdaAbsI{y_i}{b_i}^{i\in 1..n}]$$ 141 | 142 | Vamos a decir que un trait es completo cuando provea todos los atributos necesarios para que un objeto pueda ser utilizado. Y, cuando es completo, podremos definir una función $new$ como un constructor que crea un objeto con las mismas etiquetas que el trait y que asocia a cada una de ellas un método que invoca al método del trait correspondiente con su primer parámetro ligado a \texttt{self}: 143 | 144 | $$new \equalDef \lambdaAbsI{z}{[\OOAtributo{l_i}{s}{z.l_i(s)^{i\in 1..n}}]}$$ 145 | 146 | En el siguiente ejemplo trait \texttt{CompT} no es completo y, por lo tanto, si queremos hacer un $new$ de un objeto, nos devolverá un objeto inutilizable: 147 | 148 | \begin{align*} 149 | \texttt{CompT}\equalDef [~& \\ &\OOAtributo{eq}{t}{\lambda(x)\lambda(y)\lambdaIf{(x.comp(y)) == 0}{\texttt{true}}{\texttt{false}}},~\\ 150 | &\OOAtributo{leq}{t}{\lambda(x)\lambda(y)\lambdaIf{(x.comp(y)) < 0}{\texttt{true}}{\texttt{false}}} \\ 151 | ]~& 152 | \end{align*} 153 | 154 | \begin{align*} 155 | new~\texttt{CompT}\longrightarrow [~& \\ &\OOAtributo{eq}{x}{\lambda(y)\texttt{CompT}.eq(x,y)},~\\ 156 | &\OOAtributo{leq}{x}{\lambda(y)\texttt{CompT}.leq(x,y)} \\ 157 | ]~& 158 | \end{align*} 159 | 160 | Podemos ver que a $new~\texttt{CompT}$ le falta el atributo $comp$ que es utilizado dentro de las funciones del trait para realizar la comparación. 161 | 162 | El trait \texttt{Contador} mostrado a continuación es un trait completo. Si bien no puede ser usado, cuando creamos un objeto se le asignan los atributos $get$, $inc$ y $v$. $get$ e $inc$ usan a $v$ cuando son evaluados, por lo que estos dos métodos podrán ser ejecutados desde el nuevo objeto. 163 | \begin{align*} 164 | \texttt{Contador}\equalDef [~& v = 0, \\ 165 | & inc = \lambda(s) s.v := s.v + 1, \\ 166 | & get = \lambda(s) s.v \\ 167 | ]~& \\ 168 | \end{align*} 169 | \begin{align*} 170 | new~\texttt{Contador}\equalDef [~& v = Contador.v, \\ 171 | & inc = \varsigma(s) Contador.inc(s), \\ 172 | & get = \varsigma(s) Contador.get(s) \\ 173 | ]~& \\ 174 | \end{align*} 175 | 176 | \newpage 177 | Cuando un trait completo tenga dentro suyo a la función $new$, diremos que ese trait es una \textbf{clase}: 178 | \begin{align*} 179 | \texttt{C}\equalDef [~& \\ &\OOAtributo{new}{z}{[\OOAtributo{l_i}{s}{z.l_i(s)^{i\in 1..n}}]}~\\ 180 | &l_i = \lambda(x_{1})\dots\lambda(x_{n_i})B_i \\ 181 | ]~& 182 | \end{align*} 183 | \paragraph{Herencia} Cuando queremos que una clase ``herede'', lo que hacemos es crear un nuevo trait que contenga todas las etiquetas del trait original y asocie cada una de esas etiquetas al método correspondiente del trait original y le agregamos los atributos que deseamos para extenderlo. Además, modificamos el constructor $new$ para que tome en cuenta los nuevos atributos. 184 | 185 | \vspace*{5mm} 186 | \begin{align*} 187 | \texttt{Contador}\equalDef [~& 188 | new = \varsigma(z)[\OOAtributo{inc}{s}{z.inc(s)},~v = z.v,~ \OOAtributo{get}{s}{z.get(s)} ], \\ 189 | & v = \lambda(s)0, \\ 190 | & inc = \lambda(s) s.v := s.v + 1, \\ 191 | & get = \lambda(s) s.v \\ 192 | ]~& \\ 193 | \end{align*} 194 | 195 | Y su sublcase \texttt{ContadorR}: 196 | 197 | \vspace*{5mm} 198 | \begin{tabular}{ll} 199 | $\texttt{ContadorR}\equalDef [$ & 200 | $new = \varsigma(z)[$ 201 | \\ & $\quad\OOAtributo{inc}{s}{z.inc(s)},$ \\ 202 | & $\quad v = z.v,$ \\ 203 | & $\quad \OOAtributo{get}{s}{z.get(s)},$ \\ 204 | & $\quad \OOAtributo{reset}{\lambda(s)}{z.reset(s)} $ \\ 205 | & $ ],$ \\ 206 | & $v = Contador.v$ \\ 207 | & $inc = \lambda(y)\texttt{Contador}.inc(y)$ \\ 208 | & $get = \lambda(y)\texttt{Contador}.get(y)$ \\ 209 | & $reset = \lambda(s) s.v := 0,$ \\ 210 | & $]$ \\ 211 | \end{tabular} 212 | 213 | 214 | \paragraph{Otras consideraciones del lenguaje} 215 | El lenguaje que definimos se parece mucho al funcional. En la versión imperativa, donde se mantiene un store con referencias a objetos, se ofrece la función \texttt{Clone}$(a)$ que crea un nuevo objeto con las mismas etiquetas de $a$ y cada componente comparte los métodos con las componentes de $a$. 216 | 217 | Además, el lenguaje no nos deja agregar o eliminar dinámicamente métodos en un objeto y no nos deja extraer sus métodos, es decir, no es posible tener un método fuera de un objeto. 218 | 219 | Hay otras versiones de este cálculo que incluyen sistemas de tipado. 220 | -------------------------------------------------------------------------------- /soluciones_haskell_js_prolog/Practica1.hs: -------------------------------------------------------------------------------- 1 | module Practica1 where 2 | 3 | import Practica0 4 | 5 | -- Ejercicio 1 -- 6 | -- La función subtract ya esta definida en Prelude 7 | max2 ::(Float, Float) -> Float 8 | max2 (x, y) | x >= y = x 9 | | otherwise = y 10 | 11 | max2Currificada :: Float -> Float -> Float 12 | max2Currificada x y | x >= y = x 13 | | otherwise = y 14 | 15 | normaVectorial :: (Float, Float) -> Float 16 | normaVectorial (x, y) = sqrt (x^2 + y^2) 17 | 18 | normaVectorialCurrificada :: Float -> Float -> Float 19 | normaVectorialCurrificada x y = sqrt (x^2 + y^2) 20 | 21 | -- subtract ys esta definida en Prelude 22 | subtract1 :: Float -> Float -> Float 23 | subtract1 = flip (-) 24 | 25 | predecesor :: Float -> Float 26 | predecesor = subtract 1 27 | 28 | evaluarEnCero :: (Float -> b) -> b 29 | evaluarEnCero = \f -> f 0 30 | 31 | dosVeces :: (a -> a) -> (a -> a) 32 | dosVeces = \f -> f.f 33 | 34 | flipAll :: [a -> b -> c] -> [ b -> a -> c] 35 | flipAll = map flip 36 | 37 | flipRaro :: b -> ( a -> b -> c ) -> a -> c 38 | flipRaro = flip flip 39 | 40 | 41 | 42 | 43 | 44 | -- Ejercicio 2 -- 45 | ejercicio2 :: [Integer] 46 | ejercicio2 = [ x | x <- [1..3], y <- [x..3], ( x + y ) `mod` 3 == 0 ] 47 | 48 | 49 | 50 | 51 | 52 | -- Ejercicio 3 -- 53 | pitagoricas :: [(Integer, Integer, Integer)] 54 | pitagoricas = [ (a, b, c) | c <- [1..], b <-[1..c], a <- [1..c], a^2 + b^2 == c^2] 55 | 56 | 57 | 58 | 59 | 60 | -- Ejercicio 4 -- 61 | primerosPrimos :: Int -> [Int] 62 | primerosPrimos n = take n [ x | x <- [2..], esPrimo x ] 63 | 64 | 65 | 66 | 67 | 68 | -- Ejercicio 5 -- 69 | partir :: [ a ] -> [ ( [ a ], [ a ] ) ] 70 | partir xs = [ ( take i xs, drop i xs ) | i <- [ 0.. ( length xs ) ] ] 71 | 72 | 73 | 74 | 75 | 76 | -- Ejercicio 6 -- Repite listas 77 | listasQueSuman :: Int -> [[Int]] 78 | listasQueSuman 1 = [[1]] 79 | listasQueSuman x = [x] : [ (x-i) : ls | i <- [1.. x-1], ls <- listasQueSuman(i) ] 80 | 81 | -- Ejercicio 7 -- 82 | listasFinitas :: [[Int]] 83 | listasFinitas = [ ls | i <- [1..], ls <- listasQueSuman i ] 84 | 85 | -- Ejercicio 8 -- 86 | curry1 :: ((a,b) -> c) -> a -> b -> c 87 | curry1 f a b = f (a,b) 88 | 89 | uncurry1 :: (a -> b -> c) -> (a, b) -> c 90 | uncurry1 f (a, b) = f a b 91 | 92 | 93 | 94 | 95 | 96 | -- Ejercicio 9 -- 97 | -- I 98 | type DivideConquer a b = (a -> Bool) -- determina si es o no el caso trivial 99 | -> (a -> b) -- resuelve el caso trivial 100 | -> (a -> [a]) -- parte el problema en sub-problemas 101 | -> ([b] -> b) -- combina resultados 102 | -> a -- estructura de entrada 103 | -> b -- resultado-- 104 | 105 | dc :: DivideConquer a b 106 | dc esTrivial resolver repartir combinar x = 107 | if esTrivial x then 108 | resolver x 109 | else combinar (map (dc esTrivial resolver repartir combinar) (repartir x)) 110 | 111 | -- II 112 | mergesort :: Ord a => [a] -> [a] 113 | mergesort = dc ((<=1).length) 114 | id 115 | partirALaMitad 116 | (\[xs,ys] -> merge xs ys) 117 | 118 | -- III 119 | mapDC :: (a -> b) -> [a] -> [b] 120 | mapDC f = dc ((<=1).length) 121 | ( \xs -> if null xs then [] else [ f (head xs) ] ) 122 | partirALaMitad 123 | concat 124 | 125 | filterDC :: (a -> Bool) -> [a] -> [a] 126 | filterDC p = dc ((<=1).length) 127 | (\xs -> if (null xs) || (p (head xs)) then [] else xs ) 128 | partirALaMitad 129 | concat 130 | -- Auxiliares 131 | 132 | partirALaMitad :: [a] -> [[a]] 133 | partirALaMitad xs = [ take i xs, drop i xs ] 134 | where i = (div (length xs) 2) 135 | 136 | merge :: Ord a => [a] -> [a] -> [a] 137 | merge = foldr (\y rec -> (filter (<= y) rec) ++ [y] ++ (filter (>y) rec)) 138 | 139 | 140 | 141 | 142 | 143 | -- Ejercicio 10 -- 144 | -- I 145 | sumFold :: Num a => [a] -> a 146 | sumFold = foldr (+) 0 147 | 148 | elemFold :: Eq a => a -> [a] -> Bool 149 | elemFold x = foldr (\y rec -> (y==x) || rec) False 150 | 151 | masMasFold :: [a] -> [a] -> [a] 152 | masMasFold = flip (foldr (:)) 153 | -- -- masmas xs ys = foldr (\x rec-> x:rec) ys xs) 154 | 155 | mapFold :: (a->b) -> [a] -> [b] 156 | mapFold f = foldr (\x rec-> (f x):rec) [] 157 | 158 | filterFold :: (a->Bool) -> [a] -> [a] 159 | filterFold p = foldr (\x rec -> if (p x) then x:rec else rec) [] 160 | 161 | -- II 162 | -- --mejorSegun f [x] = x 163 | -- --mejorSegun f (x:xs) | f x (mejorSegun f xs) = x 164 | -- -- | otherwise = mejorSegun f xs 165 | 166 | mejorSegun :: (a -> a -> Bool) -> [a] -> a 167 | mejorSegun f = foldr1 (\x rec -> if f x rec then x else rec) 168 | 169 | 170 | 171 | -- III 172 | sumaAlt :: Num a => [a] -> a 173 | sumaAlt = foldr (-) 0 174 | 175 | -- IV 176 | sumaAlt2 :: Num a => [a] -> a 177 | sumaAlt2 = sumaAlt.reverse 178 | 179 | 180 | -- V 181 | permutaciones :: [a] -> [[a]] 182 | permutaciones = foldr (\x -> concatMap (agregarEnTodasLasPosiciones x) ) [[]] 183 | where agregarEnTodasLasPosiciones x xs = foldr (\i rec -> ((take i xs) ++ [x] ++ (drop i xs)) : rec) [] [0..(length xs)] 184 | 185 | 186 | 187 | -- Ejercicio 11 -- 188 | partes :: [a] -> [[a]] 189 | partes = foldr (\x res -> res ++ (map (x:) res)) [[]] 190 | 191 | prefijos :: [a] -> [[a]] 192 | prefijos = foldl (\rec x -> rec ++ [last rec ++ [x]]) [[]] 193 | 194 | sufijos :: [a] -> [[a]] 195 | sufijos = foldr (\x rec -> (x: head rec) : rec) [[]] 196 | 197 | sublistas :: [a] -> [[a]] 198 | sublistas xs = [] : filter (not.null) (subWithNull xs) 199 | where subWithNull = \ys -> concatMap prefijos (sufijos ys) 200 | 201 | -- Ejercicio 12 -- 202 | recr::(a->[a]->b->b)->b->[a]->b 203 | recr _ z [] = z 204 | recr f z (x:xs) = f x xs (recr f z xs) 205 | 206 | sacarUna :: Eq a => a -> [a] -> [a] 207 | sacarUna x = recr (\y ys rec -> if (x==y) then ys else y:rec) [] 208 | 209 | 210 | 211 | 212 | 213 | -- Ejercicio 13 -- 214 | genLista :: a -> (a -> a) -> Int -> [a] 215 | genLista x proximo n = foldr 216 | (\y rec -> if null rec then 217 | [x] 218 | else 219 | rec ++ [ proximo (last rec)]) 220 | [] 221 | [1.. n] 222 | 223 | desdeHasta :: Int -> Int -> [Int] 224 | desdeHasta x y = genLista x (+1) (y-x) 225 | 226 | 227 | 228 | 229 | 230 | -- Ejercicio 14 -- 231 | -- I 232 | mapPares :: (a -> b -> c) -> [(a,b)] -> [c] 233 | mapPares f = map (uncurry f) 234 | 235 | -- II 236 | armarPares :: [a] -> [b] -> [(a,b)] 237 | armarPares = 238 | foldr (\x rec-> 239 | (\ys -> if null ys then [] 240 | else (x,head ys):(rec (tail ys))) 241 | ) 242 | (\ys -> []) 243 | 244 | armarPares' :: [a] -> [b] -> [(a,b)] 245 | armarPares' = 246 | foldr 247 | (\x r h -> if null h then [] else (x, head h) : (r (tail h)) ) 248 | (\_ -> []) 249 | 250 | -- III 251 | mapDoble :: (a -> b -> c) -> [a] -> [b] -> [c] 252 | mapDoble f as = mapPares f.(zip as) 253 | 254 | 255 | 256 | 257 | 258 | -- -- Ejercicio 15 -- 259 | -- I 260 | sumaMat :: [[Int]] -> [[Int]] -> [[Int]] 261 | sumaMat = zipWith (zipWith (+)) 262 | 263 | -- II 264 | trasponer :: [[Int]] -> [[Int]] 265 | trasponer [] = [] 266 | trasponer xss = foldr (zipWith (:)) [ [] | i <- [1..length (head xss)]] xss 267 | 268 | 269 | 270 | 271 | 272 | -- Ejercicio 16 -- 273 | generate :: ([a] -> Bool) -> ([a] -> a) -> [a] 274 | generate stop next = generateFrom stop next [] 275 | 276 | generateFrom:: ([a] -> Bool) -> ([a] -> a) -> [a] -> [a] 277 | generateFrom stop next xs | stop xs = init xs 278 | | otherwise = (generateFrom stop next (xs ++ [next xs])) 279 | 280 | -- I 281 | generateBase::([a] ->Bool) ->a ->(a ->a) ->[a] 282 | generateBase stop x next = generate stop (\xs -> if (null xs) then x else (next (last xs)) ) 283 | 284 | -- II 285 | factoriales::Int ->[Int] 286 | factoriales n = 287 | generate ((==n).length) 288 | (\xs -> if null xs then 1 289 | else (last xs)*(length xs)) 290 | 291 | -- III 292 | iterateN :: Int -> (a -> a) -> a -> [a] 293 | iterateN n f x = generateBase ((>n).length) x f 294 | 295 | -- IV 296 | generateFrom1:: ([a] -> Bool) -> ([a] -> a) -> [a] -> [a] 297 | generateFrom1 stop next = last.(takeWhile (not.stop)).(iterate (\ys -> ys ++ [next ys])) 298 | 299 | 300 | 301 | 302 | 303 | -- Ejercicio 17 -- 304 | -- I 305 | foldNat :: (Integer -> a -> a) -> a -> Integer -> a 306 | foldNat _ z 0 = z 307 | foldNat f z n = f n (foldNat f z (n-1)) 308 | 309 | -- II 310 | potencia :: Integer -> Integer -> Integer 311 | potencia n m = foldNat (\x -> (n*)) n (m-1) 312 | 313 | 314 | -- Ejercicio 18 -- 315 | type Conj a = (a->Bool) 316 | 317 | -- I 318 | vacio :: Conj a 319 | vacio x = False 320 | 321 | agregar :: Eq a => a -> Conj a -> Conj a 322 | agregar x c = (\y -> (y == x) || (c x)) 323 | 324 | -- II 325 | interseccion :: Conj a -> Conj a -> Conj a 326 | interseccion c1 c2 = ( \x -> (c1 x) && (c2 x) ) 327 | 328 | union :: Conj a -> Conj a -> Conj a 329 | union c1 c2 =( \x -> (c1 x) || (c2 x) ) 330 | 331 | --III 332 | conjuntoInfinito :: Conj a 333 | conjuntoInfinito = (\x -> True) 334 | 335 | -- IV 336 | singleton :: Eq a => a -> Conj a 337 | singleton x = (==x) 338 | 339 | -- V 340 | mapConjunto :: Eq b => [a] -> (a -> b) -> Conj a -> Conj b 341 | mapConjunto xs f c = (\x -> not (null (filter (\y -> (c y) && ((f y) == x)) xs)) ) 342 | 343 | 344 | -- Ejercicio 19 -- 345 | type MatrizInfinita a = Int->Int->a 346 | 347 | identidad :: MatrizInfinita Int 348 | identidad = (\i j -> if i==j then 1 349 | else 0) 350 | 351 | cantor :: MatrizInfinita Int 352 | cantor = (\x y -> (x + y) * (x + y + 1) `div` 2 + y ) 353 | 354 | pares :: MatrizInfinita (Int, Int) 355 | pares = (\x y -> (x, y) ) 356 | 357 | -- I 358 | fila :: Int -> MatrizInfinita a -> [a] 359 | fila x m = [ m x i | i <- [1..] ] 360 | 361 | fila1::Int->MatrizInfinita a->[a] 362 | fila1 i m = map (\j -> m i j) [1..] 363 | 364 | columna :: Int -> MatrizInfinita a -> [a] 365 | columna x m = [ m i x | i <- [1..] ] 366 | 367 | columna1::Int->MatrizInfinita a->[a] 368 | columna1 j m = map (\i -> m i j) [1..] 369 | 370 | -- II 371 | trasponerInfinito :: MatrizInfinita a -> MatrizInfinita a 372 | trasponerInfinito m = (flip m) 373 | 374 | --trasponer::MatrizInfinita a->MatrizInfinita a 375 | --trasponer m = foldNat (\i rec -> mapDoble (:) (fila i) rec) (length [1..]) 376 | 377 | 378 | -- III 379 | mapMatriz :: ( a -> b ) -> MatrizInfinita a -> MatrizInfinita b 380 | mapMatriz f m = (\x y -> f (m x y)) 381 | 382 | filterMatriz :: ( a -> Bool ) -> MatrizInfinita a -> [a] 383 | filterMatriz p m = [ m j (i-j) | i <-[0..], j <-[0..i], p (m j (i-j)) ] 384 | 385 | zipWithMatriz :: (a->b->c) -> MatrizInfinita a -> MatrizInfinita b -> MatrizInfinita c 386 | zipWithMatriz f m1 m2 = (\i j -> f (m1 i j) (m2 i j)) 387 | 388 | -- IV 389 | sumaMatriz :: Num a => MatrizInfinita a -> MatrizInfinita a -> MatrizInfinita a 390 | sumaMatriz = zipWithMatriz (+) 391 | 392 | zipMatriz :: MatrizInfinita a -> MatrizInfinita b -> MatrizInfinita (a,b) 393 | zipMatriz = zipWithMatriz (\x y -> (x,y)) 394 | 395 | 396 | 397 | 398 | 399 | -- Ejercicio 20 -- 400 | data AHD a b = Hoja b 401 | | Rama a (AHD a b) 402 | | BinAHD (AHD a b) a (AHD a b) deriving Show 403 | 404 | ahdEjemplo1 :: AHD Char String 405 | ahdEjemplo1 = BinAHD (Hoja "hola") 'b' (Rama 'c' (Hoja "chau")) 406 | 407 | ahdEjemplo2 :: AHD Integer Bool 408 | ahdEjemplo2 = (BinAHD(Rama 1 (Hoja False)) 2 (BinAHD(Hoja False) 3 (Rama 5 (Hoja True)))) 409 | 410 | -- I 411 | foldAHD :: (a -> c -> c -> c) -> (a -> c -> c) -> (b -> c) -> AHD a b -> c 412 | foldAHD _ _ z (Hoja e) = z e 413 | foldAHD f g z (Rama e ar) = g e (foldAHD f g z ar) 414 | foldAHD f g z (BinAHD ar1 e ar2) = f e (foldAHD f g z ar1) (foldAHD f g z ar2) 415 | 416 | 417 | -- II 418 | mapAHD :: (a -> b) -> (c -> d) -> AHD a c -> AHD b d 419 | mapAHD f g = 420 | foldAHD (\e rec1 rec2 -> BinAHD rec1 (f e) rec2) 421 | (\e rec -> Rama (f e) rec) 422 | (\e -> Hoja (g e)) 423 | 424 | 425 | 426 | 427 | 428 | 429 | -- Ejercicio 21 -- 430 | -- data AB está definida en práctica 0 431 | 432 | -- I 433 | foldAB :: (a -> b -> b -> b) -> b -> AB a -> b 434 | foldAB _ z Nil = z 435 | foldAB f z (Bin ar1 e ar2) = f e (foldAB f z ar1) (foldAB f z ar2) 436 | 437 | 438 | -- II 439 | esNil :: AB a -> Bool 440 | esNil arbol = 441 | case arbol of 442 | Nil -> True 443 | Bin _ _ _ -> False 444 | 445 | altura :: AB a -> Integer 446 | altura = foldAB (\x rec rec1 -> 1 + rec + rec1) 0 447 | 448 | ramas :: AB a -> [[a]] 449 | ramas = foldAB 450 | (\e rec rec1 -> if (null rec) && (null rec1) then [[e]] 451 | else map (e:) (rec++rec1) 452 | ) 453 | [] 454 | 455 | nodos :: AB a -> Integer 456 | nodos = foldAB (\_ rec rec1 -> 1 + rec + rec1) 457 | 0 458 | 459 | hojas :: AB a -> Integer 460 | hojas = foldAB (\_ rec rec1 -> if (rec == 0) && (rec1 == 0) then 1 461 | else rec + rec1 462 | ) 463 | 0 464 | 465 | espejo :: AB a -> AB a 466 | espejo = foldAB (\x rec rec1 -> Bin rec1 x rec) 467 | Nil 468 | 469 | 470 | -- III Preguntar: Hay una forma de hacerlo u otra, cual quieren? La que hace medio trampa, como que noes recursion, solamente accedo a los elementos del constructor y en otras funciones (?) 471 | 472 | root :: AB a -> a 473 | root (Bin _ x _) = x 474 | 475 | izq :: AB a -> AB a 476 | izq (Bin i _ _) = i 477 | 478 | der :: AB a -> AB a 479 | der (Bin _ _ d) = d 480 | 481 | mismaEstructura :: Eq a => AB a -> AB a -> Bool 482 | mismaEstructura = 483 | foldAB (\x rec rec1 -> 484 | (\arbol -> 485 | if esNil arbol then False 486 | else (root arbol) == x && (rec (izq arbol)) && (rec1 (der arbol)) 487 | ) 488 | ) 489 | (\arbol -> esNil arbol) 490 | 491 | 492 | -- La puro fold 493 | 494 | root1 :: AB a -> a 495 | root1 = foldAB (\x _ _ -> x) undefined 496 | 497 | izq1 :: AB a -> AB a 498 | izq1 = foldAB (\_ rec _ -> rec) undefined 499 | 500 | der1 :: AB a -> AB a 501 | der1 = foldAB (\_ _ rec -> rec) undefined 502 | 503 | mismaEstructura1 :: Eq a => AB a -> AB a -> Bool 504 | mismaEstructura1 = 505 | foldAB (\x rec rec1 -> 506 | (\arbol -> 507 | if esNil arbol then False 508 | else (root arbol) == x && (rec (izq arbol)) && (rec1 (der arbol)) 509 | ) 510 | ) 511 | (\arbol -> esNil arbol) 512 | 513 | 514 | 515 | 516 | 517 | -- Ejercicio 22 -- 518 | -- I 519 | data RoseTree a = Rose a [RoseTree a] deriving Show 520 | 521 | foldRose :: (a -> [b] -> b) -> RoseTree a -> b 522 | foldRose f (Rose x xs) = f x (map (foldRose f) xs) 523 | 524 | hojasRT :: RoseTree a -> [a] 525 | hojasRT = foldRose (\x recs -> if null recs then [x] 526 | else x: (concat recs)) 527 | 528 | distancias :: RoseTree a -> [(a, Integer)] 529 | distancias = foldRose (\x recs -> if null recs then [(x,0)] 530 | else map (\(t1,t2) -> (t1, t2 + 1)) (concat recs)) 531 | 532 | alturaRT :: RoseTree a -> Integer 533 | alturaRT = foldRose (\x recs -> if null recs then 0 534 | else 1 + (max recs)) 535 | where max = mejorSegun (>) 536 | 537 | 538 | -------------------------------------------------------------------------------- /soluciones_haskell_js_prolog/practica5.js: -------------------------------------------------------------------------------- 1 | // Ejercicio 1 2 | // a) 3 | console.log("================================") 4 | console.log("Ejercicio 1") 5 | console.log("================================") 6 | 7 | // a 8 | let c1i = { 9 | r: 1, 10 | i: 1 11 | } 12 | 13 | console.log(`1.a) c1i`) 14 | console.log(c1i); 15 | console.log(' ') 16 | 17 | c1i.sumar = function(complejo){ 18 | this.r += complejo.r; 19 | this.i += complejo.i; 20 | } 21 | 22 | console.log(`1.b) c1i`) 23 | console.log( c1i) 24 | c1i.sumar(c1i) 25 | console.log(`1.b) c1i.sumar(c1i); c1i`) 26 | console.log(c1i) 27 | console.log(' ') 28 | c1i.sumar({r: -1, i:-1}); 29 | 30 | 31 | // c) 32 | 33 | c1i.sumar = function(complejo){ 34 | let nuevoComplejo = Object.assign({}, this); 35 | nuevoComplejo.r += complejo.r; 36 | nuevoComplejo.i += complejo.i; 37 | return nuevoComplejo; 38 | } 39 | 40 | console.log(`1.c) cli`); 41 | console.log(c1i); 42 | console.log(`1.c) c1i.sumar(c1i)`) 43 | console.log(c1i.sumar(c1i)); 44 | console.log(`1.c) c1i`) 45 | console.log("c1i", c1i); 46 | console.log(' ') 47 | 48 | // d) No tengo que cambiar la solucion 49 | console.log(`1.d) c1i`) 50 | console.log(c1i); 51 | console.log(`1.d) c1i.sumar(c1i).sumar(c1i)`) 52 | console.log(c1i.sumar(c1i).sumar(c1i)) 53 | console.log(`1.d) c1i`); 54 | console.log(c1i); 55 | console.log(' ') 56 | 57 | // e) 58 | let c = c1i.sumar(c1i) 59 | c.restar = function(complejo){ 60 | let nuevoComplejo = Object.assign({}, this); 61 | nuevoComplejo.r -= complejo.r; 62 | nuevoComplejo.i -= complejo.i; 63 | return nuevoComplejo; 64 | } 65 | 66 | console.log("1.e) c") 67 | 68 | console.log("1.e) c") 69 | console.log(c) 70 | console.log("1.e) c1i.restar(c)") 71 | try { 72 | c1i.restar(c); 73 | } catch(error) { 74 | console.log(error); 75 | } 76 | 77 | console.log(` `) 78 | 79 | // f) 80 | 81 | c1i.mostrar = function(){ 82 | return `${this.r} + ${(this.i == 1)? '' : this.i}i`; 83 | } 84 | 85 | console.log(`1.f) c1i.mostrar() = ${c1i.mostrar()}`) 86 | 87 | console.log("1.f) c.mostrar()") 88 | try { 89 | c.mostrar(); 90 | } catch(error) { 91 | console.log(error); 92 | } 93 | console.log(` `) 94 | 95 | 96 | 97 | 98 | 99 | console.log("================================") 100 | console.log("Ejercicio 2") 101 | console.log("================================") 102 | 103 | // a 104 | let t = {} 105 | let f = {} 106 | 107 | t.ite = function(a,b) { 108 | return a; 109 | } 110 | 111 | f.ite = function(a,b) { 112 | return b; 113 | } 114 | 115 | console.log(`2.a) t`) 116 | console.log(t); 117 | console.log(`2.a) f`) 118 | console.log(f); 119 | 120 | console.log(' ') 121 | 122 | 123 | t.mostrar = function() { 124 | return "Verdadero"; 125 | } 126 | 127 | f.mostrar = function(){ 128 | return "Falso"; 129 | } 130 | 131 | console.log(`2.b) t.mostrar() = ${t.mostrar()}`) 132 | console.log(`2.b) f.mostrar() = ${f.mostrar()}`) 133 | console.log(` `) 134 | 135 | t.not = function(){ 136 | return f; 137 | } 138 | 139 | f.not = function(){ 140 | return t; 141 | } 142 | 143 | t.and = function(otroValor) { 144 | return otroValor; 145 | } 146 | 147 | f.and = function(element) { 148 | return this; 149 | } 150 | 151 | console.log(`2.c) t.not() = ${t.not().mostrar()}`) 152 | console.log(`2.c) f.not() = ${f.not().mostrar()}`) 153 | console.log(`2.c) t.and(t) = ${t.and(t).mostrar()}`) 154 | console.log(`2.c) t.and(f) = ${t.and(f).mostrar()}`) 155 | console.log(`2.c) f.and(t) = ${f.and(t).mostrar()}`) 156 | console.log(`2.c) f.and(f) = ${f.and(f).mostrar()}`) 157 | 158 | 159 | console.log("================================") 160 | console.log("Ejercicio 3") 161 | console.log("================================") 162 | 163 | // 3.a) 164 | let Cero = {}; 165 | 166 | Cero.esCero = function(){ 167 | return true; 168 | }; 169 | 170 | Cero.succ = function(){ 171 | return new Succ(this); 172 | } 173 | 174 | 175 | function Succ(predecesor){ 176 | this.predecesor = predecesor; 177 | }; 178 | 179 | Succ.prototype.__proto__ = Cero; 180 | 181 | Succ.prototype.pred = function(){ 182 | return this.predecesor; 183 | } 184 | 185 | console.log(`3.a) Cero`) 186 | console.log(Cero); 187 | 188 | console.log(`3.a) Succ`) 189 | console.log(Succ); 190 | console.log(`3.a) Cero.succ()`) 191 | console.log(Cero.succ()); 192 | console.log(` `) 193 | 194 | // 3.b) 195 | Cero.toNumber = function(){ 196 | return 0; 197 | } 198 | 199 | Succ.prototype.toNumber = function(){ 200 | return this.pred().toNumber() + 1; 201 | } 202 | 203 | console.log(`3.b) Cero = ${Cero.toNumber()}`) 204 | console.log(`3.b)Cero.succ().succ() = ${Cero.succ().succ().toNumber}`) 205 | console.log(` `) 206 | 207 | // 3.c) 208 | Cero.for = function(f){} 209 | 210 | Succ.prototype.for = function(f){ 211 | this.pred().for(f); 212 | f.eval(this); 213 | } 214 | 215 | let funcion = { 216 | eval: function(i){ 217 | console.log(i.toNumber()) 218 | } 219 | } 220 | 221 | console.log(`3.c) f.eval`) 222 | console.log(funcion.eval) 223 | console.log(`3.c) Cero.succ().succ().for()`) 224 | Cero.succ().succ().for(funcion); 225 | 226 | console.log("================================") 227 | console.log("Ejercicio 4") 228 | console.log("================================") 229 | 230 | // a) 231 | 232 | let PuntoO = {} 233 | PuntoO.new = function (x,y) { 234 | let p = { 235 | x: x, 236 | y: y 237 | } 238 | 239 | p.mostrar = function(){ 240 | return PuntoO.mostrar(this); 241 | } 242 | 243 | p.moverX = function(x) { 244 | return PuntoO.moverX(x, this); 245 | } 246 | 247 | return p 248 | } 249 | 250 | PuntoO.mostrar = function(o) { 251 | return `Punto(${o.x},${o.y})` 252 | } 253 | 254 | let mostrarAux = PuntoO.mostrar 255 | 256 | let p = PuntoO.new(1,2); 257 | console.log(`4.a) p.mostrar() = ${p.mostrar()}`); 258 | 259 | PuntoO.mostrar = function(){ 260 | return 'unPunto' 261 | } 262 | console.log(`4.a) Redefinimos Punto.mostrar`) 263 | console.log(PuntoO.mostrar) 264 | console.log(`4.a) p.mostrar() = ${p.mostrar()}`) 265 | console.log(` `) 266 | 267 | PuntoO.mostrar = mostrarAux 268 | // 4.b) 269 | 270 | let PuntoColoreadoO = {}; 271 | PuntoColoreadoO.new = function(x,y){ 272 | let p = PuntoO.new(x,y) 273 | 274 | p.color = 'rojo' 275 | p.mostrar = function() { 276 | return PuntoColoreadoO.mostrar(this) 277 | } 278 | 279 | return p 280 | } 281 | 282 | PuntoColoreadoO.mostrar = function(o){ 283 | return PuntoO.mostrar(o); 284 | } 285 | 286 | 287 | let pColoreado = PuntoColoreadoO.new(1,2) 288 | 289 | console.log(`4.b) pColoreado.mostrar() = ${pColoreado.mostrar()}`) 290 | PuntoO.mostrar = function(){ 291 | return 'unPunto' 292 | } 293 | console.log(`4.b) Redefinimos Punto.mostrar`) 294 | console.log(PuntoO.mostrar) 295 | console.log(`4.b) p.mostrar() = ${pColoreado.mostrar()}`) 296 | 297 | PuntoColoreadoO.mostrar = function() { 298 | return 'unPuntoColoreado'; 299 | } 300 | console.log(`4.b) Definimos PuntoColoreado.mostrar`) 301 | console.log(PuntoColoreadoO.mostrar) 302 | console.log(`4.b) p.mostrar() = ${pColoreado.mostrar()}`) 303 | console.log(` `) 304 | 305 | 306 | PuntoColoreadoO.mostrar = function(o){ 307 | return PuntoO.mostrar(o); 308 | } 309 | 310 | PuntoO.mostrar = mostrarAux 311 | PuntoColoreadoO.coloreadoMostrar = function(o){ 312 | return PuntoO.mostrar(o) 313 | } 314 | 315 | // 4.c) 316 | PuntoColoreadoO.newC = function(x, y, color) { 317 | let p = this.new(x,y) 318 | p.color = color 319 | return p 320 | } 321 | 322 | console.log(`4.c) PuntoColoreado`) 323 | console.log(PuntoColoreadoO) 324 | console.log(` `) 325 | 326 | // 4.d) 327 | let p1 = PuntoO.new(1 ,2) ; 328 | let pc1 = PuntoColoreadoO.new(1 ,2) ; 329 | 330 | PuntoO.moverX = function(x, o){ 331 | o.x += x 332 | } 333 | 334 | PuntoO.new = function(x,y) { 335 | let p = { 336 | x: x, 337 | y: y 338 | } 339 | 340 | p.mostrar = function() { 341 | return PuntoO.mostrar(this) 342 | } 343 | 344 | p.moverX = function(x) { 345 | return PuntoO.moverX(x, this) 346 | } 347 | return p 348 | } 349 | 350 | let p2 = PuntoO.new (1 ,2) ; 351 | let pc2 = PuntoColoreadoO.new (1 ,2) ; 352 | 353 | console.log(`4.d) p1 = ${p1.mostrar()}`) 354 | console.log(`4.d) p1.moverX(1)`) 355 | 356 | try { 357 | p1.moverX(1) 358 | console.log(p1.mostrar()) 359 | } catch(error) { 360 | console.log(error) 361 | } 362 | console.log(`4.d) pc1 = ${pc1.mostrar()}`) 363 | console.log(`4.d) pc1.moverX(1)`) 364 | 365 | try { 366 | pc1.moverX(1) 367 | console.log(pc1.mostrar()) 368 | } catch(error) { 369 | console.log(error) 370 | } 371 | console.log(`4.d) p2 = ${p2.mostrar()}`) 372 | console.log(`4.d) p2.moverX(1)`) 373 | 374 | try { 375 | p2.moverX(1) 376 | console.log(p2.mostrar()) 377 | } catch(error) { 378 | console.log(error) 379 | } 380 | console.log(`4.d) pc2 = ${pc2.mostrar()}`) 381 | console.log(`4.d) pc2.moverX(1)`) 382 | 383 | try { 384 | pc2.moverX(1) 385 | console.log(pc2.mostrar()) 386 | } catch(error) { 387 | console.log(error) 388 | } 389 | 390 | console.log("================================") 391 | console.log("Ejercicio 5") 392 | console.log("================================") 393 | 394 | function Punto(x, y){ 395 | this.x = x; 396 | this.y = y; 397 | } 398 | 399 | Punto.prototype.mostrar = function(){ 400 | return `Punto(${this.x},${this.y})` 401 | } 402 | 403 | let mostrar5Aux = Punto.prototype.mostrar 404 | 405 | let p5 = new Punto(1,2); 406 | console.log(`5.a) p.mostrar() = ${p5.mostrar()}`); 407 | 408 | Punto.prototype.mostrar = function(){ 409 | return 'unPunto' 410 | } 411 | 412 | console.log(`5.a) Redefinimos Punto.prototype.mostrar`) 413 | console.log(Punto.prototype.mostrar) 414 | console.log(`5.a) p.mostrar() = ${p5.mostrar()}`) 415 | console.log(` `) 416 | 417 | Punto.prototype.mostrar = mostrar5Aux 418 | 419 | // 5.b) 420 | function PuntoColoreado(x,y, color) { 421 | this.x = x 422 | this.y = y 423 | this.color = color 424 | } 425 | 426 | PuntoColoreado.prototype.__proto__ = Punto.prototype 427 | 428 | let pColoreado5 = new PuntoColoreado(1,2) 429 | 430 | console.log(`5.b) pColoreado.mostrar() = ${pColoreado5.mostrar()}`) 431 | 432 | Punto.prototype.mostrar = function(){ 433 | return 'unPunto' 434 | } 435 | 436 | console.log(`5.b) Redefinimos Punto.prototype.mostrar`) 437 | console.log(Punto.prototype.mostrar) 438 | console.log(`5.b) p.mostrar() = ${pColoreado5.mostrar()}`) 439 | 440 | PuntoColoreado.prototype.mostrar = function() { 441 | return 'unPuntoColoreado'; 442 | } 443 | console.log(`5.b) Definimos PuntoColoreado.prototype.mostrar`) 444 | console.log(PuntoColoreado.prototype.mostrar) 445 | console.log(`5.b) p.mostrar() = ${pColoreado5.mostrar()}`) 446 | console.log(` `) 447 | 448 | delete PuntoColoreado.prototype.mostrar 449 | Punto.prototype.mostrar = mostrar5Aux 450 | 451 | console.log(`5.c) PuntoColoreado`) 452 | console.log(PuntoColoreado) 453 | console.log(` `) 454 | 455 | // 4.d) 456 | let p15 = new Punto(1 ,2) ; 457 | let pc15 = new PuntoColoreado(1 ,2) ; 458 | 459 | Punto.prototype.moverX = function(x){ 460 | this.x += x 461 | } 462 | 463 | let p25 = new Punto(1 ,2) ; 464 | let pc25 = new PuntoColoreado(1 ,2) ; 465 | 466 | console.log(`4.d) p1 = ${p15.mostrar()}`) 467 | console.log(`4.d) p1.moverX(1)`) 468 | 469 | try { 470 | p15.moverX(1) 471 | console.log(p15.mostrar()) 472 | } catch(error) { 473 | console.log(error) 474 | } 475 | console.log(`4.d) pc1 = ${pc15.mostrar()}`) 476 | console.log(`4.d) pc1.moverX(1)`) 477 | 478 | try { 479 | pc15.moverX(1) 480 | console.log(pc15.mostrar()) 481 | } catch(error) { 482 | console.log(error) 483 | } 484 | console.log(`4.d) p2 = ${p25.mostrar()}`) 485 | console.log(`4.d) p2.moverX(1)`) 486 | 487 | try { 488 | p25.moverX(1) 489 | console.log(p2.mostrar()) 490 | } catch(error) { 491 | console.log(error) 492 | } 493 | console.log(`4.d) pc2 = ${pc25.mostrar()}`) 494 | console.log(`4.d) pc2.moverX(1)`) 495 | 496 | try { 497 | pc25.moverX(1) 498 | console.log(pc25.mostrar()) 499 | } catch(error) { 500 | console.log(error) 501 | } 502 | 503 | 504 | 505 | console.log("================================") 506 | console.log("Ejercicio 6") 507 | console.log("================================") 508 | 509 | function C1(){}; 510 | C1.prototype.g = " Hola "; 511 | 512 | function C2 () {}; 513 | C2.prototype.g = " Mundo "; 514 | 515 | let a = new C1(); 516 | C1.prototype = C2.prototype; 517 | let b = new C1(); 518 | 519 | console.log(`6.a)`) 520 | console.log(a.g); 521 | console.log(b.g); 522 | 523 | function C1b(){}; 524 | C1b.prototype.g = " Hola "; 525 | 526 | function C2b () {}; 527 | C2b.prototype.g = " Mundo "; 528 | 529 | let ab = new C1b(); 530 | C1b.prototype.g = C2b.prototype.g; 531 | let bb = new C1b(); 532 | 533 | console.log(`6.b)`) 534 | console.log(ab.g); 535 | console.log(bb.g); 536 | 537 | console.log("================================") 538 | console.log("Ejercicio 7") 539 | console.log("================================") 540 | 541 | // 7.a) 542 | let o = { 543 | a: 1, 544 | b: function(x){ 545 | return x + a 546 | } 547 | }; 548 | 549 | let o1 = Object.create(o); 550 | o1.c = true; 551 | 552 | let o1Keys = new Array; 553 | let o1Values = new Array; 554 | 555 | for (let k in o1){ 556 | o1Keys.push(k); 557 | o1Values.push(o1[k]) 558 | } 559 | 560 | console.log(`7.a)`) 561 | console.log(o1Keys) 562 | console.log(o1Values) 563 | console.log(` `) 564 | // 7.b) 565 | function extender(o1, o2){ 566 | let res = Object.assign({},o2); 567 | 568 | for(var key in o1) { 569 | if(res[key] == undefined) res[key] = o1[key] 570 | } 571 | 572 | return res; 573 | } 574 | 575 | console.log(`7.b) extender({a:1, b:true, c:"Hola"}, {b:1, d:"Mundo"})`) 576 | console.log(extender({a:1, b:true, c:"Hola"}, {b:1, d:"Mundo"})) 577 | console.log(` `) 578 | 579 | // 7.c) 580 | 581 | let A = { 582 | inicializar: function(n,a){ 583 | this.nombre = n 584 | this.apellido = a 585 | this 586 | }, 587 | 588 | presentar: function(){ 589 | return this.nombre + " " + this.apellido; 590 | } 591 | } 592 | 593 | let B = Object.create(A); 594 | B.saludar = function(){ 595 | alert("Hola"+this.presentar()+".") 596 | }; 597 | 598 | let a7 = Object.create(A); 599 | a7.inicializar("Juan", "Perez"); 600 | 601 | let b7 = Object.create(B); 602 | b7.inicializar("Pedro","Juarez"); 603 | 604 | B.presentar = A.presentar 605 | delete A.presentar 606 | 607 | console.log(`7.c) a.presentar`) 608 | try { 609 | a7.presentar() 610 | } catch(error){ 611 | console.log(error) 612 | } 613 | 614 | console.log(`7.c) b.presentar`) 615 | console.log(b7.presentar()) 616 | console.log(` `) 617 | // 7.d) 618 | let A7d = function(){} 619 | A7d.prototype.inicializar = function(n,a){ 620 | this.nombre = n 621 | this.apellido = a 622 | return this 623 | }, 624 | 625 | A7d.prototype.presentar = function(){ 626 | return this.nombre + " " + this.apellido; 627 | } 628 | 629 | let B7d = function(){} 630 | B7d.prototype.__proto__ = A7d.prototype; 631 | B7d.prototype.saludar = function(){ 632 | alert("Hola"+this.presentar()+".") 633 | }; 634 | 635 | let a7d = new A7d().inicializar("Juan", "Perez"); 636 | let b7d = new B7d().inicializar("Pedro","Juarez"); 637 | 638 | B7d.prototype.presentar = A7d.prototype.presentar 639 | delete A7d.prototype.presentar 640 | 641 | console.log(`7.d) a.presentar`) 642 | try { 643 | a7d.presentar() 644 | } catch(error){ 645 | console.log(error) 646 | } 647 | 648 | console.log(`7.d) b.presentar`) 649 | console.log(b7d.presentar()) 650 | -------------------------------------------------------------------------------- /apuntes/secciones/logica_primer_orden.tex: -------------------------------------------------------------------------------- 1 | \section{Lógica de primer orden} 2 | Definimos un método para probar que una proposición es una tautología. Sin embargo, todavía no tiene todo el poder que podría tener. Nos gustaría, dada una proposición con literales, saber que valor deberían tomar esos literales para que la proposición sea una tautología. 3 | 4 | Para esto debemos dotar de semántica a los literales y proveer un mecanismo que nos permita inferir los valores que deben componer a cada uno de ellos. 5 | 6 | \subsection{Repaso} 7 | Un \textbf{lenguaje de primer orden} (LPO) $\mathcal{L}$ consiste en: 8 | \begin{enumerate} 9 | \item Un conjunto numerable de \textbf{constantes} $c_0,c_1,\dots$ 10 | \item Un conjunto numerable de \textbf{símbolos de función} con aridad $n > 0$ $f_0, f_1,\dots$ 11 | \item Un conjunto numerable de \textbf{símbolos de predicado} con aridad $n\geq 0$, $P_0,P_1,\dots$. 12 | \end{enumerate} 13 | 14 | \subsubsection{Términos de primer orden} 15 | Sea $\mathcal{V} = \{x_0,x_1,\dots\}$ un conjunto numerable de variables y $\mathcal{L}$ un lenguaje de primer orden. El conjunto de \textbf{$\mathcal{L}$-términos} se define inductivamente como: 16 | \begin{itemize} 17 | \item Toda constante de $\mathcal{L}$ y toda variable es un $\mathcal{L}$-término. 18 | \item Si $t_1,\dots,t_n\in \mathcal{L}$-términos y $f$ es un símbolo de función de aridad $n$, entonces $$f(t_1,\dots,t_n)\in \mathcal{L}\text{-términos}$$ 19 | \end{itemize} 20 | 21 | \subsubsection{Fórmulas átomicas} 22 | Sea $\mathcal{V}$ un conjunto numerable de variables y $\mathcal{L}$ un lenguaje de primer orden. El conjunto de \textbf{$\mathcal{L}$-fórmulas átomicas} se define inductivamente como: 23 | \begin{enumerate} 24 | \item Todo símbolo de predicado de aridad $O$ es una $\mathcal{L}$-fórmula átomica. 25 | \item Si $t_1,\dots,t_n\in\mathcal{L}$-términos y $P$ es un símbolo de predicado de aridad $n$, entonces $P(t_1,\dots,t_n)$ es una $\mathcal{L}$-fórmula átomica. 26 | \end{enumerate} 27 | \subsubsection{Fórmulas de primer orden} 28 | Sea $\mathcal{V}$ un conjunto numerable de variables y $\mathcal{L}$ un lenguaje de primer orden. El conjunto de \textbf{$\mathcal{L}$-fórmulas} se define inductivamente como: 29 | \begin{enumerate} 30 | \item Toda $\mathcal{L}$-fórmula átomica es $\mathcal{L}$-fórmula. 31 | \item Si $A,B\in \mathcal{L}$-fórmula, entonces $\lnot A$, $(A\land B)$, $(A\lor B)$, $(A\supset B)$ y $A\iff B$ son $\mathcal{L}$-fórmulas. 32 | \item Para toda variable $x_i$ y cualquier $\mathcal{L}$-fórmula $A$, $\forall x_i.A$ t $\exists x_i.A$ son $\mathcal{L}$-fórmulas. 33 | 34 | \end{enumerate} 35 | \subsubsection*{Variables libres y ligadas} 36 | 37 | Las variables pueden ocurrir \textbf{libres} o \textbf{ligadas}. En este lenguaje, los cuantificadores ligan variable y usaremos $FV(A)$ y $BV(A)$ parar referirnos a las variables libres y ligadas, respectivamente, de $A$. 38 | 39 | Cuando $FV(A) = \emptyset$ diremos que $A$ es una \textbf{sentencia}. 40 | 41 | Una fórmula $A$ está \textbf{rectificada} si $FV(A)$ y $BV(A)$ son disjuntos, es decir si todos los cuantificadores que aparecen en $A$ ligan variables distintas. Además, toda fórmula se puede \textbf{rectificar} a una fórmula equivalente renombrando sus variables. 42 | 43 | \subsubsection{Estructuras de primer orden} 44 | Dado un lenguaje $\mathcal{L}$, una \textbf{estructura para $\mathcal{L}$}, \textbf{M}, es un par \textbf{M} $=(M, I)$ donde 45 | \begin{itemize} 46 | \item $M$ (\textbf{dominio}) es un conjunto no vacío 47 | \item $I$ (\textbf{función de interpretación}) asigna funciones y predicados sobre $M$ a símbolos del lenguaje $\mathcal{L}$ de la siguiente manera: 48 | \begin{enumerate} 49 | \item Para toda constante $c$, $I(c)\in M$. 50 | \item Para todo $f$ de aridad $n > O$, $I(f):M^n\to M$ 51 | \item Para todo predicado $P$ de aridad $n \geq 0$, $I(P) : M^n \to\{\textbf{T}, \textbf{F}\}$ 52 | 53 | Sea $M$ una estructura para $\mathcal{L}$. Una \textbf{asignación} es una función $s:\mathcal{V}\to M$ y, si $a\in M$, escribimos $s[x \leftarrow a]$ para denotar la asignación que se comporta igual que $s$ salvo en el elemento $x$, en cuyo caso retorna $a$. 54 | \end{enumerate} 55 | \end{itemize} 56 | 57 | \subsubsection{Satisfactibilidad} 58 | La relación $s \models_M A$ establece que la asignación $s$ satisface la fórmula $A$ en la estructura $M$. Y se define usando inducción estructural en $A$: 59 | 60 | \begin{align*} 61 | &s \models_\textbf{M} P(t_1,\dots,t_n)&&~sii~P(s(t_1),\dots,s(t_n))&&&\\ 62 | &s \models_\textbf{M} \lnot A &&~sii ~s \not{\models}_\textbf{M} A &&&\\ 63 | &s \models_\textbf{M} (A \lor B)&&~sii~s \models_\textbf{M} A \text{ o } s\models_\textbf{M} B&&&\\ 64 | &s \models_\textbf{M} (A \land B)&&~sii~s \models_\textbf{M} A \text{ y } s\models_\textbf{M} B&&&\\ 65 | &s \models_\textbf{M} (A \supset B)&&~sii~s\not\models_\textbf{M} A \text{ o } s\models_\textbf{M} B&&&\\ 66 | &s \models_\textbf{M} (A \iff B)&&~sii~(s\models_\textbf{M} A \text{ sii } s\models_\textbf{M} B)&&&\\ 67 | &s \models_\textbf{M} (A \supset B)&&~sii~s\not\models_\textbf{M} A \text{ o } s\models_\textbf{M} B&&&\\ 68 | &s \models_\textbf{M} \forall x_i.A &&~sii~s[x_i\leftarrow a]\models_\textbf{M} A \text{ para todo } a\in \textbf{M}&&&\\ 69 | &s \models_\textbf{M} \exists x_i.A &&~sii~s[x_i\leftarrow a]\models_\textbf{M} A \text{ para algún } a\in \textbf{M}&&&\\ 70 | \end{align*} 71 | 72 | \newpage 73 | \subsubsection{Validez}\label{logica::primerOrden::validez} 74 | \begin{itemize} 75 | \item Una fórmula $A$ es \textbf{satisfactible en M} si y solo si existe una asiganción $s$ tal que $s\models_\textbf{M} A$ 76 | 77 | \item Una fórmula $A$ es \textbf{satisfactible} si y solo si existe un \textbf{M} tal que A es satisfactible en \textbf{M}. En caso contrario se dice que $A$ es insatisfactible. 78 | 79 | \item Una fórmula $A$ es \textbf{válida en M} si y solo si $s \models_\textbf{M} A$, para toda asigación $s$. 80 | 81 | \item $A$ es valida si y solo si $\lnot A$ es insatisfactible. 82 | \end{itemize} 83 | 84 | \subsection{El método de resolución} 85 | 86 | El \textbf{teorem de Church} asegura que \textbf{no} existe un algoritmo que pueda determinar si una fórmula de primer orden es válida. Por lo que el método de resolución será parcialmente computable, es decir que si la sentencia que deseamos resolver es insatisfactible entonces hallaremos una refutación a la misma, en caso contrario puede ser que no se detenga. 87 | 88 | Para resolver una fórmula, el método tomará su forma clausal e irá agregando resolventes hasta que el conjunto contenga a la cláusula vacía. 89 | 90 | \subsubsection{Forma de la fórmula} 91 | Dada una fórmula $A$, el primer pasoe es escribirla en forma clausal siguiendo estos pasos: 92 | \begin{enumerate} 93 | \item Eliminar las implicaciones, es decir, si aparece una clausula de la forma $(A\supset B)$, reescribirla como $(\lnot A \lor B)$. 94 | 95 | \item Pasar a \textbf{forma normal negada}. 96 | \item Pasar a \textbf{forma normal prenexa}. 97 | \item Pasar a \textbf{forma normal de Skolem}. 98 | \item Pasar a \textbf{forma normal conjuntiva}. 99 | \item \textbf{Distribuir} cuantificadores universales. 100 | \end{enumerate} 101 | 102 | \subsubsection*{Forma normal negada} 103 | El conjunto de fórmulas en \textbf{forma normal negada} (NNF) se define inductivamente como: 104 | 105 | \begin{enumerate} 106 | \item Para cada fórmula atómica $A$, $A$ y $\lnot A$ están en NNF. 107 | \item Si $A,B\in$ NNF, etnoces $(A\lor B),(A\land B) \in$ NNF. 108 | 109 | \item Si $A\in$ NNF, entonces $(\forall x.A),(\exists x. A)\in$ NNF. 110 | \end{enumerate} 111 | 112 | En otras palabras, son todas las fórmulas en las que si aparece una negación, entonces esta está aplicada a una formula atómica del lenguaje. 113 | 114 | Los remplazos que se hacen para pasar una formula a FNN son: 115 | 116 | \begin{multicols}{2} 117 | $$\lnot(A\land B) \iff \lnot A \land \lnot B$$ 118 | $$\lnot(A\lor B) \iff \lnot A \lor \lnot B$$ 119 | \vfill\null 120 | \columnbreak 121 | $$\lnot\lnot A \iff A$$ 122 | $$\lnot\forall x.A \iff \exists x.\lnot A$$ 123 | $$\lnot\exists x.A \iff \forall x.\lnot A$$ 124 | \end{multicols} 125 | 126 | \subsubsection*{Forma normal prenexa} 127 | Son las fórmulas de la forma $Q_1x_1\dots Q_nx_n.B$, $n\geq 0$, donde $B$ no tiene cuantificadores, $x_1,\dots,x_n$ son variables y $Q_i \in \{\forall,\exists\}$. 128 | 129 | Sea $A$ una fórmula en forma normal negativa, entonces valen las siguientes equivalencias: 130 | 131 | \begin{multicols}{2} 132 | $$(\forall x.A)\land B \iff \forall x.(A\land B)$$ 133 | $$(A\land\forall x.B) \iff \forall x.(A\land B)$$ 134 | $$(\exists x.A)\land B \iff \exists x.(A\land B)$$ 135 | $$(A\land\exists x.B) \iff \exists x.(A\land B)$$ 136 | 137 | $$(\forall x.A)\lor B \iff \forall x.(A\lor B)$$ 138 | $$(A\lor\forall x.B) \iff \forall x.(A\lor B)$$ 139 | $$(\exists x.A)\lor B \iff \exists x.(A\lor B)$$ 140 | $$(A\lor\exists x.B) \iff \exists x.(A\lor B)$$ 141 | \end{multicols} 142 | 143 | Cuando una fórmula tenga dos o más cuantificadores que liguen variables con el mismo nombre, entonces debemos renombrar cada una de esas variables con nombres distintos para poder realizar la transformación. 144 | 145 | \subsubsection{Forma normal de Skolem} 146 | Dada una fórmula en forma normal prenexa, debemos pasarla a forma normal de Skolem usando un proceso llamado \textbf{solemización}. El objetivo de esta transformación es eliminar los cuantificadores existenciales de un fórmula sin alterar su sastifactibilidad. 147 | 148 | La idea es que al eliminar el existencial remplazemos cada aparición de la variable que ligaba por un ``testigo'' que es una constante nueva del lenguaje de primer orden que depende de las demás variables libres de la fórmula. Por ejemplo, si tenemos la fórmula $\exists x.P(x)$, su forma skolemizada será $P(c)$ con $c$ una nueva constante del lenguaje que llamaremos \textbf{parámetro}. 149 | 150 | En fórmulas más grandes, cada ocurrencia de una subfórmula $\exists x.B$ en $A$ se remplaza por $B\{ x \leftarrow f(x_1,\dots,x_n)\}$ donde: 151 | \begin{itemize} 152 | \item $\{\bullet \leftarrow \bullet\}$ es la operación usual de sustitución. 153 | \item $f$ es un símbolo de función nuevo y las $x_1,\dots, x_n$, son las variables libres en $B$ de las que depende $x$. 154 | \end{itemize} 155 | 156 | Ahora, si bien el resultado de skolemizar una fórmula preserva la sastifactibilidad, no preserva validez. Por ejemplo, la fórmula $\exists x.(P(a) \supset P(x))$ es válida, sin embargo, su skolemización \\ $P(a)\supset P(b)$ no lo es. (Ver la definición de validez en \ref{logica::primerOrden::validez}). 157 | 158 | \subsubsection*{Definición formal} 159 | Sea $A$ una sentencia rectificada en forma normal negada, la \textbf{forma normal de Skolem de A} (\textbf{SK(A)}) se define recursivamente como sigue: 160 | 161 | Sea $A'$ cualquier subfórmula de $A$, 162 | \begin{itemize} 163 | \item Si $A'$ es una fórmula atómica o su negación, \textbf{SK}$(A') = A'$. 164 | \item Si $A'$ es de la forma $(B\star C)$ con $\star \in \{\land,\lor\}$, entonces $\textbf{SK}(A') = (\textbf{SK}(B)\star \textbf{SK}(C))$. 165 | \item Si $A'$ es de la forma $\forall x.B$, entonces $\textbf{SK}(A') = \forall x.\textbf{SK}(B)$. 166 | \item Si $A'$ es de la forma $\exists x.B$ y $\{x,y_1,\dots,y_m\}$ son las variables libres de $B$, entonces: 167 | \begin{enumerate} 168 | \item Si $m>0$, crear un \textbf{símbolo de función de Skolem}, $f_x$ de aridad $m$ y definir: 169 | 170 | $$\textbf{SK}(A') = \textbf{SK}(B\{ x \leftarrow f(y_1,\dots,y_m)\})$$ 171 | 172 | \item Si $m=0$, crear una nueva \textbf{constante de Skolem} $c_x$ y 173 | 174 | $$\textbf{SK}(A') = \textbf{SK}(B\{ x \leftarrow c_x\})$$ 175 | 176 | \end{enumerate} 177 | \end{itemize} 178 | 179 | \subsubsection*{Forma clausal} 180 | Una vez que tenemos una formula en forma normal prenexa skolemizada, es decir tiene la siguiente forma: 181 | $$\forall x_1\dots\forall x_n.B$$ 182 | 183 | Pasamos $B$ a \textbf{forma normal conjuntiva} \ref{Logica::Proposicional::FNC} como si fuese una fórmula proposicional y distribuimos los cuantificadores sobre cada conjunción, obteniendo así una conjunción de \textbf{cláusulas} 184 | 185 | $$\forall x_1\dots\forall x_n.C_1\land\dots\land\forall x_1\dots\forall x_n.C_m$$ 186 | 187 | donde cada $C_i$ es una disyunción de literales. Luego, podemos escribirla de la siguiente forma: 188 | 189 | $$ \{C_1,\dots,C_m\}$$ 190 | 191 | \subsubsection{Regla de resolución} 192 | A diferencia de la lógica de primer orden, tendremos literales que cuando son negados podrían contradecir a otro literal que no sea exactamente el mismo. Por ejemplo, si tenemos la siguiente proposición $\{\{\{P(x)\},\{\{\lnot P(a)\}\}$. La primer cláusula, nos dice que vale $P(x)$ para todo $x$ y la segunda nos dice que $P(a)$ no vale, esto es una contradicción que deberíamos poder resolver. 193 | 194 | Debemos \textbf{unificar} estas dos expresiones con el algoritmo de Martelli-Montanari. Por lo que en cada paso, elegiremos las cláusulas que queremos resolver, buscaremos un MGU que nos permita modificarlas y la resolvente será la resolvente de ambas expresiones con el MGU aplicado. 195 | 196 | Entonces, la regla es: 197 | $$\frac{\{\blue{B_1,\dots,B_k},A_1,\dots,A_n\}\hspace*{5mm}\{\blue{\lnot D_1,\dots,\lnot D_k},A_1,\dots,A_n\}}{\red{\sigma(\{A_1,\dots A_m, C_1,\dots,C_n\})}}$$ 198 | 199 | donde $\sigma$ es el \textbf{unificador más general} (MGU) de $\{B_1,\dots,B_k,\lnot D_1,\dots,\lnot D_k\}$ y \\ $\sigma(\{A_1,\dots A_m, C_1,\dots,C_n\})$ es el \textbf{resolvente}. 200 | 201 | Cuando usamos $\sigma$, debemos tener en cuenta que todas las cláusulas usan variables distintas, por lo que si hay dos cláusulas que usan variables con el mismo nombre es conveniente renombrarlas para evitar confusiones. 202 | 203 | \subsubsection{Método de resolución} 204 | 205 | Ya tenemos la regla de resolución para fórmulas de la lógica de primer orden. El método de resolución es análogo al de la lógica proposicional. En cada paso buscaremos una resolvente que podamos agregar al conjunto y haremos esto hasta que la resolvente que agregamos sea $\Box$ (la cláusula vacía). 206 | 207 | A diferencia del método de lógica de primer orden, en cada paso no solo agregaremos una resolvente al conjunto sino que además definimos una sustitución que nos permitirá unificar distintos términos de la expresiones. 208 | 209 | \paragraph{Ejemplo:} Queremos probar que $\{C_1, C_2, C_3\}$ es insatisfactible con 210 | \begin{itemize} 211 | \item $C_1 = \{\lnot P(z_1,a), \lnot P(z_1,x), \lnot P(x,z_1)\}$ 212 | \item $C_2 = \{P(z_2,f(z_2)), P(z_2,a)\}$ 213 | \item $C_3 = \{P(f(z_3),z_3), P(z_3,a)\}$ 214 | \end{itemize} 215 | 216 | \begin{centrado} 217 | \begin{enumerate} 218 | \item De $C_1$ y $C_2$ con $\{z_1\leftarrow a, x\leftarrow a, z_2\leftarrow a,\}$ tenemos $C_4 = \{ P(a,f(a))\}$ 219 | \item De $C_1$ y $C_2$ con $\{z_1\leftarrow a, x\leftarrow a, z_3\leftarrow a,\}$ tenemos $C_5 = \{ P(f(a),a)\}$ 220 | \item De $C_1$ y $C_5$ con $\{z_1 \leftarrow f(a), x\leftarrow a\}$: $C_6 = \{ \lnot P(a,f(a))\}$ 221 | \item De $C_4$ y $C_6$: $\Box$. 222 | \end{enumerate} 223 | \end{centrado} 224 | \subsubsection{Regla de resolución binaria} 225 | 226 | $$\frac{\{\blue{B_1},A_1,\dots,A_n\}\hspace*{5mm}\{\blue{\lnot D_1},A_1,\dots,A_n\}}{\red{\sigma(\{A_1,\dots A_m, C_1,\dots,C_n\})}}$$ 227 | 228 | \hspace*{5mm} 229 | Si intentamos refutar $\{\{P(x), P(y)\}, \{\lnot P(v), \lnot P(w)\}\}$ solo con esta regla nos encontraremos con que no podremos encontrar una secuencia de resolventes que termine en la cláusula $\Box$. 230 | 231 | \subsubsection*{Regla de factoriazción} 232 | La regla de factorización resuelve este problema permitiendonos extraer de una cláusula un literal represente a cada uno de los literales que la componen. Es decir, un literal que pueda ser unificado con cada uno de los literales de la cláusula. 233 | 234 | $$\frac{\{\blue{B_1,\dots,B_k},A_1,\dots,A_n\}}{\red{\sigma(\{B_1,A_1,\dots A_m\})}}$$ 235 | 236 | \hspace*{5mm} 237 | 238 | Entonces con esta regla podemos usar $\{P(z)\}$ como resolvente para la cláusula $\{P(x), P(y)\}$ y la demostración del ejemplo anterior quedaría de la siguiente forma: 239 | 240 | \begin{enumerate} 241 | \item $\{\{P(x), P(y)\}, \{\lnot P(v), \lnot P(w)\}\}$ 242 | \item $\{\{P(x), P(y)\}, \{\lnot P(v), \lnot P(w)\}, \blue{\{P(z)\}}\}$ (por la regla de factorización sobre la primer cláusula) 243 | \item $\{\{P(x), P(y)\}, \{\lnot P(v), \lnot P(w)\}, \{P(z)\}, \blue{\{\lnot P(u)\}}\}$ (por la regla de factorización sobre la segunda cláusula) 244 | \item $\{\{P(x), P(y)\}, \{\lnot P(v), \lnot P(w)\}, \{P(z)\}, \{\lnot P(u)\}, \Box\}$ 245 | \end{enumerate} -------------------------------------------------------------------------------- /apuntes/secciones/inferencia_de_tipos.tex: -------------------------------------------------------------------------------- 1 | \section{Inferencia de tipos} 2 | Queremos modificar el lenguaje de cálculo lambda para que las expresiones no necesiten las notaciones de tipos explicitas. Para esto, debemos definir términos a partir de los cuales se pueda \textbf{inferir} la información faltante. Esto es, debemos poder convertirlos en términos bien tipados del cálculo lambda sin ningún problema. 3 | 4 | Este nuevo lenguaje nos evitará la sobrecarga de tener que declarar y manipular todos los tipos al momento de escribir un programa. Un compilador deberá realizar la inferencia de tipos antes de compilar el program. 5 | 6 | \subsubsection*{Términos} 7 | El lenguaje sin tipos tendrá todos los términos del lenguaje $\lambda$ con el que estuvimos trabajando hasta ahora, con la diferencia de que si en ellos había una notación de tipo, entonces la obviamos: 8 | 9 | \begin{equation*} 10 | \begin{split} 11 | M~::=~&x \\ 12 | |~~~&true~|~false~|~\lambdaIf{M}{P}{Q} \\ 13 | |~~~&0~|~succ(0)~|~isZero(M) \\ 14 | |~~~& \lambdaAbsI{x}{M}~|~M~N~|~\lambdaFix{M} 15 | \end{split} 16 | \end{equation*} 17 | 18 | Si bien la mayoría de los términos son iguales a los originales, necesitaríamos alguna forma de convertir los términos del lambda cálculo a no tipados y viceversa. 19 | 20 | \paragraph{Función Erase:} Dado un término del lambda cálculo, \textbf{elimina} las anotaciones de tipos de las abstracciones que contenga. Por ejemplos: 21 | 22 | $$\Erase(\lambdaAbs{x}{Nat}{\lambdaAbs{f}{Nat\to Nat}{f~x}}) = \lambdaAbsI{x}{\lambdaAbsI{f}{f~x}}$$ 23 | 24 | \paragraph{Chequeos de tipo:} 25 | Realizar el chequeo de tipo es determinar, para un término estándar (del lenguaje $\lambda$ tipado) $M$, si existe $\Gamma$ y $\sigma$ tales que $\judgeType{\Gamma}{M}{\sigma}$ es derivable. Osea que nos indica si $M$ es un término tipable o no. Solo hay que seguir la estructura sintáctica de $M$ para reconstruir una derivación de juicio. 26 | 27 | \subsubsection*{Inferencia de tipos:} Dado un término $U$ sin notaciones de tipo, se trata hallar un término estándar (con anotaciones de tipos) $M$ bien tipado que sea equivalente. Osea tal que: 28 | \begin{enumerate} 29 | \item $\judgeType{\Gamma}{M}{\sigma}$ para algún contexto $\Gamma$ y algún tipo $\sigma$, y 30 | \item $\Erase(M) = U$ 31 | \end{enumerate} 32 | 33 | Si encontramos este $M$, $U$ será de tipo $\sigma$- Sino, $U$ será una expresión no tipable en nuestro lenguaje. 34 | 35 | 36 | \subsubsection{Variables de tipo} 37 | Una \textbf{variables de tipo} s es una variable que representa una expresión de tipo arbitraria e indica que tendremos una solución válida sin importar por que expresión de tipo la remplacemos. 38 | 39 | Debemos agregar esta nueva expresión a las expresiones de tipo del cálculo lambda: 40 | 41 | $$\sigma,\tau~::=~\text{s}~|~Nat~|~Bool~|~\sigma\to\tau$$ 42 | 43 | Supongamos que tenemos la expresión $U = \lambdaAbsI{x}{x}$. En este caso, $U$ puede ser la función identidad de cualquier tipo. 44 | Entonces, la expresión $M=\lambdaAbs{x}{\textbf{s}}{x}$ es el resultado de la inferencia de $U$ (\textbf{s} pudiendo ser cualquier tipo de nuestro lenguaje). 45 | 46 | 47 | 48 | \subsection{Sustitución de tipos} 49 | Una función $S$ de sustitución es una función que mapea variables de tipo en expresiones de tipo y puede ser aplicada a expresiones de tipos, términos y contextos de tipado. 50 | 51 | Describimos $S$ usando la notación $\{\sigma_1/t_1,\dots,\sigma_n/t_n\}$. Esto significa que la variable $t_i$ debe ser remplazada por $\sigma_i$. 52 | 53 | \paragraph{Conjunto soporte de $S$:} Conjunto $\{t_1,\dots,t_n\}$ que contiene a todas las variables que afecta $S$. 54 | 55 | \paragraph{Ejemplos:} 56 | \begin{itemize} 57 | \item Si $S = \{ Bool/t \}$, entonces $S(\lambdaAbs{x}{\text{t}}{x}) = \lambdaAbs{x}{ Bool}{x}$ y el conjunto soporte de $S$ es $\{t\}$. 58 | \item La sustitución cuyo soporte es $\emptyset$, es la \textbf{sustitución identidad} 59 | \end{itemize} 60 | 61 | \paragraph{Instancia de juicio de tipado:} 62 | Si tenemos dos juicios de tipado $\judgeType{\Gamma}{M}{\sigma}$ y $\judgeType{\Gamma'}{M'}{\sigma'}$ tales que $$S(\judgeType{\Gamma}{M}{\sigma}) = \judgeType{S\Gamma}{SM}{S\sigma} =\judgeType{\Gamma'}{M'}{\sigma'}$$, entonces decimos que $\judgeType{\Gamma'}{M'}{\sigma'}$ es instancia de $\judgeType{\Gamma}{M}{\sigma}$. ) 63 | 64 | \paragraph{Composición de sustituciones} La composición de sustituciones de $S$ y $T$, denotada $S\circ T$, es la sustitución que se comporta como sigue: 65 | 66 | $$(S\circ T)(\sigma) = S(T\sigma)$$ 67 | 68 | \paragraph{Preorden de sustituciones} Una sustitución $S$ es \textbf{más general} que $T$ si existe una sustitución $U$ tal que $T = U\circ S$, es decir, si $T$ es una instancia de $S$. 69 | 70 | 71 | \subsubsection{Unificación} 72 | El algoritmo de inferencia que vamos a proponer analiza un término (sin notaciones de tipos) a partir de sus subtérminos. Una vez obtenida la información de cada uno de ellos, debe determinar si es \textbf{consistente} y, si lo es, \textbf{sintetizar} la información del término original a partir de ésta. 73 | 74 | Para realizar la síntesis, debemos \textbf{compatibilizar} la información de tipos de cada subtérmino. Por cada una de las variables del término, tenemos que tomar los tipos que le asigno cada uno de ellos y \textbf{unificarlos}. Es decir, debemos encontrar una sustitución $S$ que nos permita remplazar los tipos que dió cada subexpresión por un tipo único. 75 | 76 | 77 | \paragraph{Ecuación de unificación} Es una expresión de la forma $\sigma_1 \equalDot \sigma_2$ cuya solución es una sustitución tal que $S\sigma_1 = S\sigma_2$. Por lo general tendremos un conjunto de ecuaciones de unificación y la solución a dicho conjunto será la sustitución que unifica todas las expresiones. 78 | 79 | \paragraph{Unificador más general (MGU):} Una sustitución $S$ que resuelva $\{\sigma_1 \equalDot \sigma_1',\dots,\sigma_n \equalDot \sigma_n'\}$ y que es más general que cualquier otra sustitución que la resuelva. 80 | 81 | \paragraph{Teorema} Si $\{\sigma_1 \equalDot \sigma_1',\dots,\sigma_n \equalDot \sigma_n'\}$ tiene solución, entonces existe un MGU y además es único salvo renombre de variables. 82 | 83 | \subsubsection{Algoritmo de unificación de Martelli-Montanari} 84 | Es un algoritmo no deterministico que, a través de \textbf{reglas de simplificación}, nos permite reescribir un conjunto de ecuaciones de unificación (\textit{goal}) $\{\sigma_1 \equalDot \sigma_1',\dots,\sigma_n \equalDot \sigma_n'\}$. 85 | 86 | Si, cuando el algortimo termina, conseguimos una secuencia de reescrituras que terminan en un \textit{goal} vacío, entonces la corrida fue \textbf{exitosa}, los pasos en los que realizamos sustituciones serán soluciones parciales al \textit{goal} original y la composición de todas ellas será su MGU. Si no sucede esto, entonces la secuencia será \textbf{fallida}. 87 | 88 | \subsubsection{Reglas de reducción} 89 | 90 | \begin{enumerate} 91 | \item \textbf{Descomposición} 92 | 93 | $\{\sigma_1\to\sigma_2 \equalDot\tau_1\to\tau_2\}\cup G\mapsto \{\sigma_1\equalDot\tau_1,~\sigma_2 \equalDot\tau_2\}\cup G$ 94 | \item \textbf{Eliminación de par trivial} 95 | 96 | $\{Nat \equalDot Nat\}\cup G\mapsto G$ 97 | 98 | $\{ Bool \equalDot Bool\}\cup G\mapsto G$ 99 | 100 | $\{\text{s} \equalDot\text{s}\}\cup G\mapsto G$ 101 | \item \textbf{Swap} Si $\sigma$ no es una variable de tipo, 102 | 103 | $\{\sigma \equalDot\text{s}\}\cup G\mapsto \{\text{s}\equalDot\sigma\}\cup G$ 104 | 105 | \item \textbf{Eliminación de variable} Si $s\notin FV(\sigma)$ 106 | 107 | $\{\text{s}\equalDot\sigma\}\cup G\mapsto_{\sigma/s} G[\sigma/s]$ 108 | 109 | \item \textbf{Falla} Sea $T =\{( Bool,Nat), (Nat, \sigma_1\to\sigma_2), ( Bool, \sigma_1\to\sigma_2)\}$ y $T^{-1}$ el conjunto con cada tupla de $T$ invertida. Si $(\sigma,\tau)\in T\cup T^{-1}$: 110 | 111 | $\{\sigma\equalDot\tau\}\cup G\mapsto \red{\texttt{falla}}$. 112 | 113 | \item \textbf{Occur Check} Si $s\neq\sigma$ y $s\in FV(\sigma)$ 114 | 115 | $\{\text{s}\equalDot\sigma\}\cup G\mapsto \red{\texttt{falla}}$ 116 | \end{enumerate} 117 | 118 | \subsubsection{Propiedades del algoritmo} 119 | El algoritmo de Martinelli-Montanari siempre termina. Sea $G$ un conjunto de pares, entonces: 120 | \begin{itemize} 121 | \item Si $G$ tiene un unificador, el algoritmo termina exitosamente y retorna un MGU. 122 | \item Si $G$ no tiene un unificador, el algoritmo termina con \red{\texttt{falla}}. 123 | \end{itemize} 124 | 125 | \subsubsection{Ejemplo de aplicación} 126 | \begin{equation*} 127 | \begin{split} 128 | &\{(Nat\to r)\to(r\to u) \equalDot t\to(s\to s)\to t\} 129 | \mapsto^1 \{Nat\to r\equalDot t,~r\to u\equalDot (s\to s)\to t\} \\ 130 | &\mapsto^3 \{t\equalDot Nat\to r,~r\to u\equalDot (s\to s)\to t\} 131 | \mapsto^4_{Nat\to r/t} \{r\to u\equalDot (s\to s)\to (Nat\to r)\} \\ 132 | &\mapsto^1 \{r\equalDot(s\to s),~u\equalDot Nat\to r\} 133 | \mapsto^4_{s\to s/r} \{u\equalDot Nat\to (s\to s)\} 134 | \mapsto^4_{Nat\to(s\to s)/u} \emptyset \\ 135 | \end{split} 136 | \end{equation*} 137 | 138 | Entonces, el MGU es 139 | 140 | $\{Nat\to(s\to s)/u\}\circ\{s\to s/r\}\circ\{Nat\to r/t\} = \{Nat\to(s\to s)/u,~s\to s/r,~Nat\to (s\to s)/t\}$ 141 | 142 | \subsection{Función de inferencia \texorpdfstring{$\mathbb{W}$}{W}} 143 | Dada una expresión $U$ sin notación de tipos, la función $\mathbb{W}$, devolverá un juicio de tipado con una expresión tipada $M$ que corresponde a $U$. Esta función será ejecutada de manera recursiva sobre las sub-expresiones de $U$ y sustituirá, si es posible, los tipos de cada una de ellas para que tengan ``sentido'' en $U$. 144 | 145 | 146 | 147 | 148 | \subsubsection{Propiedades deseables de \texorpdfstring{$\WFunc$}{W}} 149 | Dado un término $U$, $\WFunc(U)$ nos devolverá, si tiene éxito, una terna de tres elementos que contendrá un contexto de tipado $\Gamma$ una expresión $M$ y un $\sigma$ (notamos $\WFunc(U) = \judgeType{\Gamma}{M}{\sigma}$). 150 | 151 | Queremos que $\WFunc$ sea \textbf{correcto} y \textbf{completo}. 152 | 153 | \paragraph{Correctitud} Si $\WFunc(U) = \judgeType{\Gamma}{M}{\sigma}$ entonces vale que: 154 | \begin{itemize} 155 | \item $\Erase(M) = U$ y 156 | \item $\judgeType{\Gamma}{M}{\sigma}$ es derivable. 157 | \end{itemize} 158 | 159 | \paragraph{Completitud} Si $\judgeType{\Gamma}{M}{\sigma}$ es derivable y $\Erase(M) = U$ entonces $\WFunc(U)$ tiene éxito y produce un juicio $\judgeType{\Gamma'}{M'}{\sigma'}$ que es instancia de $\judgeType{\Gamma}{M}{\sigma}$. 160 | 161 | \subsubsection{Algoritmo de inferencia} 162 | $\WFunc$ va a hacer recusión sobre la estructura de $U$. Primero la vamos a definir para las construcciones más simples y, luego, para las compuestas. Además, usaremos el algoritmo de unificación para combinar los resultados de los pasos recursivos y, así, obtener un tipado consistente. 163 | 164 | \subsubsection{Constantes y variables} 165 | \begin{equation*} 166 | \begin{split} 167 | \WFunc(\red{true}) &\equalDef \judgeType{\emptyset}{true}{Bool} \\ 168 | \WFunc(\red{false}) &\equalDef \judgeType{\emptyset}{false}{Bool} \\ 169 | \WFunc(\red{x}) &\equalDef \judgeType{\{x:s\}}{x}{s}, \text{ \textit{s} variable fresca } \\ 170 | \WFunc(\red{0}) &\equalDef \judgeType{\emptyset}{0}{Nat} \\ 171 | \end{split} 172 | \end{equation*} 173 | 174 | \subsubsection{Caso \texorpdfstring{\textit{succ}}{succ}} 175 | $\WFunc(\red{succ(U)}) \equalDef \judgeType{S\Gamma}{S~succ(M)}{Nat}$ 176 | \begin{centrado} 177 | \begin{itemize} 178 | \item $\WFunc(U) = \judgeType{\Gamma}{M}{\tau}$ 179 | \item $S = MGU\{\tau\equalDot Nat\}$ 180 | \end{itemize} 181 | \end{centrado} 182 | 183 | \subsubsection{Caso \texorpdfstring{\textit{pred}}{pred}} 184 | $\WFunc(\red{pred(U)}) \equalDef \judgeType{S\Gamma}{S~pred(M)}{Nat}$ 185 | \begin{centrado} 186 | \begin{itemize} 187 | \item $\WFunc(U) = \judgeType{\Gamma}{M}{\tau}$ 188 | \item $S = MGU\{\tau\equalDot Nat\}$ 189 | \end{itemize} 190 | \end{centrado} 191 | 192 | \subsubsection{Caso \texorpdfstring{\textit{isZero}}{isZero}} 193 | $\WFunc(\red{isZero(U)}) \equalDef \judgeType{S\Gamma}{S~isZero(M)}{Bool}$ 194 | \begin{centrado} 195 | \begin{itemize} 196 | \item $\WFunc(U) = \judgeType{\Gamma}{M}{\tau}$ 197 | \item $S = MGU\{\tau\equalDot Nat\}$ 198 | \end{itemize} 199 | \end{centrado} 200 | 201 | \subsubsection{Caso \texorpdfstring{\textit{ifThenElse}}{ifThenElse}} 202 | $\WFunc(\red{\lambdaIf{U}{V}{W}}) \equalDef \judgeType{S\Gamma_1\cup S\Gamma_2\cup S\Gamma_3}{S~(\lambdaIf{M}{P}{Q})}{S\sigma}$ 203 | \begin{centrado} 204 | \begin{itemize} 205 | \item $\WFunc(U) = \judgeType{\Gamma_1}{M}{\rho}$ 206 | \item $\WFunc(V) = \judgeType{\Gamma_2}{P}{\sigma}$ 207 | \item $\WFunc(W) = \judgeType{\Gamma_3}{Q}{\tau}$ 208 | \item $S = MGU\{\sigma_1\equalDot \sigma_2~|~x:\sigma_1\in\Gamma_i~\land~x:\sigma_2\in\Gamma_j,~i\neq j\}\cup\{\sigma\equalDot\tau\,~\rho\equalDot Bool\}$ 209 | \end{itemize} 210 | \end{centrado} 211 | 212 | \subsubsection{Caso aplicación} 213 | $\WFunc(\red{U~V}) \equalDef \judgeType{S\Gamma_1\cup S\Gamma_2}{S~(M~N)}{St}$ 214 | \begin{centrado} 215 | \begin{itemize} 216 | \item $\WFunc(U) = \judgeType{\Gamma_1}{M}{\tau}$ 217 | \item $\WFunc(V) = \judgeType{\Gamma_2}{N}{\rho}$ 218 | \item $S = MGU\{\sigma_1\equalDot \sigma_2~|~x:\sigma_1\in\Gamma_i~\land~x:\sigma_2\in\Gamma_j,~i\neq j\}\cup\{\tau\equalDot\rho\to t\}$ con $t$ variable fresca 219 | \end{itemize} 220 | \end{centrado} 221 | 222 | \subsubsection{Caso abstracción} 223 | $$\WFunc(\red{\lambdaAbsI{x}{U}}) \equalDef \judgeType{\Gamma \backslash\{x:\tau\}}{\lambdaAbs{x}{\tau}{M}}{\tau\to\rho}$$ 224 | 225 | 226 | Sea $\WFunc(U) = \judgeType{\Gamma}{M}{\rho}$, si $\Gamma$ tiene información de tipos para $x$, es decir $x:\tau\in\Gamma$ para algún $\tau$, entonces: 227 | 228 | $$\WFunc(\red{\lambdaAbsI{x}{U}}) \equalDef \judgeType{\Gamma \backslash\{x:\tau\}}{\lambdaAbs{x}{\tau}{M}}{\tau\to\rho}$$ 229 | 230 | Si $\Gamma$ no tiene información de tipos para $x$ ($x\notin \text{Dom}(\Gamma)$), entonces elegimos una variable fresca $s$ y 231 | 232 | $$\WFunc(\red{\lambdaAbsI{x}{U}}) \equalDef \judgeType{\Gamma}{\lambdaAbs{x}{s}{M}}{s\to\rho}$$ 233 | 234 | \subsubsection{Caso \texorpdfstring{\textit{fix}}{fix}} 235 | $\WFunc(\red{\lambdaFix{(U)}}) \equalDef \judgeType{S\Gamma}{S~\lambdaFix{(M)}}{St}$ 236 | \begin{centrado} 237 | \begin{itemize} 238 | \item $\WFunc(U) = \judgeType{\Gamma_1}{M}{\tau}$ 239 | \item $S = MGU\{\tau\equalDot t\to t\}$ con $t$ variable fresca 240 | \end{itemize} 241 | \end{centrado} 242 | 243 | \subsubsection{Complejidad del algoritmo} 244 | Tanto la unificación como la inferencia para cálculo lambda se puede realizar en tiempo lineal. Sin embargo, el tipo principal asociado a un término sin anotaciones puede ser \red{exponencial} en el tamaño del término. 245 | 246 | \subsubsection{Extensión del algoritmo a nuevos tipos} 247 | Para extender el algoritmo a otros tipos, debemos agregar los casos correspondientes teniendo en cuenta que los llamados recursivos devuelven un contexto, un término y un tipo sobre los que no podemos asumir nada. 248 | Si la nueva regla tiene tipos iguales o contextos repetidos, debemos unificarlos. Y si la regla liga alguna variable entonces vamos a poder dividir en dos casos: 249 | \begin{itemize} 250 | \item Si alguno de los contextos recursivos tiene información sobre esa variable, entonces sacamos su tipo del contexto que la contenga. 251 | \item Sino, le asignamos una variable fresca de tipo. 252 | \end{itemize} 253 | 254 | Si la regla tiene restricciones adicionales, se incorporan como posibles fallas. 255 | 256 | \subsubsection{Extensión del algoritmo para listas} 257 | $\WFunc([]) = \judgeType{\emptyset}{\List{t}}{t}$ con $t$ variable fresca. 258 | 259 | $\WFunc(U_1::U_2) = \judgeType{S\Gamma_1\cup S\Gamma_2}{S(M_1::M_2)}{S[\sigma_1]}$ 260 | 261 | \begin{centrado} 262 | \begin{itemize} 263 | \item $\WFunc(U_i) = \judgeType{\Gamma_i}{M_i}{\sigma_i}$ 264 | \item $S = MGU\{\sigma_1\equalDot \sigma_2~|~x:\sigma_1\in\Gamma_i~\land~x:\sigma_2\in\Gamma_j,~i\neq j\}\cup\{[\sigma_1]\equalDot\sigma_2\} $ 265 | \end{itemize} 266 | \end{centrado} 267 | 268 | 269 | $\WFunc(\lambdaListCase{U}{U_2}{U_3}) =$ 270 | 271 | \quad$\judgeType{S\Gamma_1\cup S\Gamma_2\cup S\Gamma_3\backslash\{h,t\}}{S(\lambdaListCase{M_1}{M_2}{M_3})}{S\sigma_2}$ 272 | 273 | \begin{centrado} 274 | \begin{itemize} 275 | \item $\WFunc(U_i) = \judgeType{\Gamma_i}{M_i}{\sigma_i}$ con $i = 1,2,3$ 276 | \item $S = MGU\{\sigma_1\equalDot \sigma_2~|~x:\sigma_1\in\Gamma_i~\land~x:\sigma_2\in\Gamma_j,~i\neq j\}\cup\{\sigma_1\equalDot [t_1],~t_1\equalDot \tau_h,~\tau_t\equalDot \sigma_1,~\sigma_2\equalDot\sigma_3\} $ con 277 | \[ \tau_h = \begin{cases} 278 | \sigma_h & \text{si } h:\sigma_h\in\Gamma_3 \\ 279 | t_2 & \text{sino} \\ 280 | \end{cases} \hspace*{5mm}\text{ y }\hspace*{5mm} 281 | \tau_t = \begin{cases} 282 | \sigma_t & \text{si } t:\sigma_t\in\Gamma_3 \\ 283 | t_2 & \text{sino} \\ 284 | \end{cases} 285 | \] 286 | \end{itemize} 287 | \end{centrado} -------------------------------------------------------------------------------- /practicas_solucion/practica_7.tex: -------------------------------------------------------------------------------- 1 | 2 | \documentclass[10pt,a4paper]{article} 3 | \input{header} 4 | 5 | \setcounter{section}{7} 6 | 7 | \begin{document} 8 | \title{PLP - Práctica 7: Programación Lógica} 9 | 10 | \date{\today} 11 | 12 | \author{Gianfranco Zamboni} 13 | 14 | \maketitle 15 | \setcounter{page}{1} 16 | 17 | 18 | \section*{El motor de búsqueda de prolog} 19 | 20 | \subsection{Ejercicio 1} 21 | \subsubsection*{Base de conocimiento:} 22 | 23 | \begin{multicols}{2} 24 | \begin{centrado2} 25 | \begin{minted}[tabsize=4]{prolog} 26 | padre(juan, carlos). %(1) 27 | padre(juan, luis). %(2) 28 | padre(carlos, daniel). %(3) 29 | padre(carlos, diego). %(4) 30 | \end{minted} 31 | \end{centrado2} 32 | \begin{centrado2} 33 | \begin{minted}[tabsize=4]{prolog} 34 | padre(luis, pablo). %(5) 35 | padre(luis, manuel). %(6) 36 | padre(luis, ramiro). %(7) 37 | abuelo(X,Y) :- %(8) 38 | padre(X,Z), 39 | padre(Z,Y). 40 | \end{minted} 41 | \end{centrado2} 42 | \end{multicols} 43 | 44 | \paragraph{I.} La consulta \prolog{abuelo(X, manuel)}, devuele \prolog{X = juan}. 45 | 46 | \subsubsection*{II.} 47 | \begin{multicols}{2} 48 | \begin{centrado2} 49 | \begin{minted}[tabsize=4]{prolog} 50 | hijo(X, Y) :- %(9) 51 | padre(Y, X). 52 | 53 | hermano(X, Y) :- %(10) 54 | padre(Z, X), 55 | padre(Z, Y), 56 | X \= Y. 57 | \end{minted} 58 | \end{centrado2} 59 | \vfill\null 60 | \columnbreak 61 | \begin{centrado2} 62 | \begin{minted}[tabsize=4]{prolog} 63 | descendiente(X, Y) :- %(11) 64 | hijo(X,Y). 65 | descendiente(X,Y) :- %(12) 66 | hijo(X, Z), 67 | descendiente(Z, Y). 68 | \end{minted} 69 | \end{centrado2} 70 | \end{multicols} 71 | 72 | \paragraph{IV.} \prolog{abuelo(juan,X)} 73 | \paragraph{V.} \prolog{hermano(pablo,X)} 74 | \paragraph{VII.} \prolog{ancestro(juan,X)} devuelve \prolog{X = juan} por la primer regla y luego, si se pide otro resultado, se cuelga porque \prolog{Z} no está bien instanciado. 75 | \paragraph{VIII.} Con dar vuelta las condiciones de la segunda regla se arregla este problema 76 | \begin{centrado} 77 | \begin{minted}[tabsize=4]{prolog} 78 | ancestro(X, X). \\ 79 | ancestro(X, Y) :- padre(X, Z), ancestro(Z, Y). 80 | \end{minted} 81 | \end{centrado} 82 | 83 | \newpage 84 | \subsection{Ejercicio 2} 85 | \paragraph{I.} 86 | \begin{center} 87 | \begin{forest} 88 | [$\lnot\prolog{vecino(5,Y,[5,6,5,3])}$, 89 | [$\Box \{\prolog{Y}\leftarrow \prolog{6}\}$,edge label={node[midway,left=2mm,font=\footnotesize] {$(1)~\prolog{X}\leftarrow \prolog{5},~\prolog{Y}\leftarrow\prolog{6},\prolog{LS}\leftarrow\prolog{[5,3]}$}}, 90 | ] 91 | [$\lnot\prolog{vecino(5,Y,[6,5,3])}$,edge label={node[midway,right=2mm,font=\footnotesize] {$(2)~ \prolog{X}\leftarrow \prolog{5},~\prolog{Y}\leftarrow\prolog{Y},\prolog{W}\leftarrow\prolog{5},\prolog{LS}\leftarrow\prolog{[6,5,3]}$}} 92 | [$\lnot\prolog{vecino(5,Y,[5,3])}$,edge label={node[midway,right=2mm,font=\footnotesize] {$(2)~ \prolog{X}\leftarrow \prolog{5},~\prolog{Y}\leftarrow\prolog{Y},\prolog{W}\leftarrow\prolog{6},\prolog{LS}\leftarrow\prolog{[5,3]}$}}, 93 | [$\Box \{\prolog{Y}\leftarrow \prolog{3}\}$,edge label={node[midway,left=2mm,font=\footnotesize] {$(1)~\prolog{X}\leftarrow \prolog{5},~\prolog{Y}\leftarrow\prolog{3},\prolog{LS}\leftarrow\prolog{[]}$}}, 94 | ] 95 | [$\lnot\prolog{vecino(5,Y,[3])}$,edge label={node[midway,right=2mm,font=\footnotesize] {$(2)~ \prolog{X}\leftarrow \prolog{5},~\prolog{Y}\leftarrow\prolog{Y},\prolog{W}\leftarrow\prolog{5},\prolog{LS}\leftarrow\prolog{[3]}$}}, 96 | [$\lnot\prolog{vecino(5,Y,[])}$,edge label={node[midway,right=2mm,font=\footnotesize] {$(2)~ \prolog{X}\leftarrow \prolog{5},~\prolog{Y}\leftarrow\prolog{Y},\prolog{W}\leftarrow\prolog{3},\prolog{LS}\leftarrow\prolog{[]}$}}, 97 | [$\falla$] 98 | ] 99 | ] 100 | ] 101 | ] 102 | ] 103 | \end{forest} 104 | \end{center} 105 | 106 | \paragraph{II.} En este caso, si invertimos las reglas, obtendremos exactamente los mismos resultado y el árbol generado por prolog, es el espejo del inciso anterior. 107 | 108 | \subsection{Ejercicio 3} 109 | \subsubsection*{Bases de conocimiento} 110 | \begin{minted}[tabsize=4]{prolog} 111 | natural(0). 112 | natural(suc(X)) :- natural(X). 113 | 114 | menorOIgual(X, suc(Y)) :- menorOIgual(X, Y). 115 | menorOIgual(X,X) :- natural(X). 116 | \end{minted} 117 | 118 | \paragraph{I.} Prolog unifica \prolog{menorOIgual(0,X)} con la regla \prolog{menorOIgual(X, suc(Y))} remplazando \prolog{X} (de la regla) por \prolog{0} e instanciando el \prolog{X} de la consulta con \prolog{suc(Y)}, obteniendo la resolvente \prolog{menorOIgual(0, Y)} que se resuelve de la misma manera. Entonces, entra en un ciclo infinito en el que siempre unifica con la primer regla. 119 | \paragraph{II.} Esto se debe a que Prolog no tiene suficiente información sobre \prolog{X} como para descartar la primer regla (\prolog{X} no está correctamente instanciada) por lo que siempre es posible hacerla coincidir con cualquier regla. 120 | 121 | \paragraph{III.} Otra vez, con cambiar el orden de evaluación de las reglas, el problema se arregla: 122 | \begin{minted}[tabsize=4]{prolog} 123 | menorOIgual(X,X) :- natural(X). 124 | menorOIgual(X, suc(Y)) :- menorOIgual(X, Y). 125 | \end{minted} 126 | 127 | \section*{\ Estructuras, instanciación y reversibilidad} 128 | 129 | \subsection{Ejercicio 4} 130 | \begin{centrado} 131 | \begin{minted}[tabsize=4]{prolog} 132 | %concatenar(?Lista1, ?Lista2, ?Lista3) 133 | concatenar([], Lista2, Lista2). 134 | concatenar([X | T1], Lista2, [X| T3]) :- 135 | concatenar(T1, Lista2, T3). 136 | \end{minted} 137 | \end{centrado} 138 | 139 | \subsection{Ejercicio 5} 140 | \begin{multicols}{2} 141 | \paragraph{I.} 142 | \begin{centrado2} 143 | \begin{minted}[tabsize=4]{prolog} 144 | %last(?L, ?U) 145 | last([ X ], X ). 146 | last([ _ | T ], Y) :- last(T,Y). 147 | \end{minted} 148 | \end{centrado2} 149 | \paragraph{II.} 150 | \begin{centrado2} 151 | \begin{minted}[tabsize=4]{prolog} 152 | %tienenLaMismaLongitud(+L, +L1) 153 | tienenLaMismaLongitud(L1, L2) :- 154 | length(L1, N ), 155 | length(L2, N ). 156 | 157 | %reverse(+L, -L1) 158 | reverse([],[]). 159 | reverse( [ X | T ], R) :- 160 | tienenLaMismaLongitud([X | T], R), 161 | reverse(T, RT ), 162 | append(RT, [ X ], R). 163 | \end{minted} 164 | \end{centrado2} 165 | \paragraph{III.} 166 | \begin{centrado2} 167 | \begin{minted}[tabsize=4]{prolog} 168 | %maxlista(+L, -M). 169 | maxlista([E],E). 170 | maxlista([E|T],E):- 171 | maxlista(T,M),E>=M. 172 | maxlista([E|T],M):- 173 | maxlista(T,M),E==M. 179 | minlista([E|T],E):- 180 | minlista(T,M),E== 1. 216 | \end{minted} 217 | \end{centrado2} 218 | \paragraph{VII.} 219 | \begin{centrado2} 220 | \begin{minted}[tabsize=4]{prolog} 221 | %pertenece(?X, +L). 222 | pertenece(X, [X|_]). 223 | pertenece(X, [Y|T]):- 224 | Y \= X, 225 | pertenece(X,T). 226 | \end{minted} 227 | \end{centrado2} 228 | \end{multicols} 229 | 230 | \subsection{Ejercicio 6} 231 | \begin{centrado} 232 | \begin{minted}[tabsize=4]{prolog} 233 | aplanar([],[]). 234 | aplanar([ [] | T ], Res) :- 235 | aplanar(T, Res). 236 | aplanar([ [X | T1 ] | T ], Res) :- 237 | aplanar([ X | T1 ], Y), 238 | aplanar(T, RecT), 239 | append(Y, RecT, Res). 240 | aplanar([ X | T ], [X | Res]) :- 241 | not(is_list(X)), 242 | aplanar(T, Res). 243 | \end{minted} 244 | \end{centrado} 245 | 246 | \newpage 247 | \subsection{Ejercicio 7} 248 | \paragraph{I.} 249 | \begin{centrado} 250 | \begin{minted}[tabsize=4]{prolog} 251 | %palindromo(+L, -L1) 252 | palindromo(L, L1) :- 253 | reverse(L, A), 254 | append(L,A,L1). 255 | \end{minted} 256 | \end{centrado} 257 | 258 | \paragraph{II.} 259 | \begin{centrado} 260 | \begin{minted}[tabsize=4]{prolog} 261 | %doble(+L, -L1) 262 | doble([], []). 263 | doble([ X | T], [X, X | Rec ]) :- 264 | doble(T, Rec). 265 | \end{minted} 266 | \end{centrado} 267 | 268 | \paragraph{III.} 269 | \begin{centrado} 270 | \begin{minted}[tabsize=4]{prolog} 271 | %iesimo(?I, +L, -X) 272 | iesimoAux(1, [X | _], X). 273 | iesimoAux(I, [_ | T], Y) :- 274 | I1 is I - 1, 275 | iesimo(I1, T, Y). 276 | 277 | iesimo(I, L, X) :- 278 | length(L, N), 279 | between(1,N, I), 280 | iesimoAux(I, L, X). 281 | \end{minted} 282 | \end{centrado} 283 | 284 | \subsection{Ejercicio 8} 285 | \paragraph{I.} Se debe instanciar \prolog{X} en un valor especifico. Entonces devuelve todos los números a partir de ese valor. Si se instancia \prolog{Y} en un valor menor que \prolog{X}, entonces se cuelga porque siempre se puede unificar con la segunda regla. Si se instancia \prolog{Y} en un valor mayor, entonces devolverá como primer resultado el valor de \prolog{Y} y luego se colgará por la misma razón que antes. 286 | 287 | Y si no se instancia \prolog{X} entonces tira error porque no tiene suficiente información sobre la variable como para realizar unificación. 288 | 289 | \paragraph{II.} 290 | \begin{centrado} 291 | \begin{minted}[tabsize=4]{prolog} 292 | %desde2(+X,?Y) 293 | desde2(X, Y) :- 294 | nonvar(Y), 295 | Y >= X. 296 | desde2(X,Y) :- 297 | var(Y), 298 | desde(X,Y). 299 | \end{minted} 300 | \end{centrado} 301 | 302 | \newpage 303 | \subsection{Ejercicio 9} 304 | \paragraph{I.} 305 | \begin{centrado} 306 | \begin{minted}[tabsize=4]{prolog} 307 | %interseccionAux(+L1, +L2, +L3, -L4) 308 | interseccionAux([], _, _, []). 309 | interseccionAux([ X | T ], L2, Usados, Resultado) :- 310 | not(member(X, L2)), 311 | interseccionAux(T, L2, Usados, Resultado). 312 | interseccionAux([ X | T ], L2, Usados, [ X | L4 ]) :- 313 | member(X, L2), 314 | not(member(X, Usados)), 315 | interseccionAux(T, L2, [ X | Usados], L4). 316 | interseccionAux([ X | T ], L2, Usados, L4 ) :- 317 | member(X, Usados), 318 | interseccionAux(T, L2, Usados, L4). 319 | 320 | %intersección(+L1, +L2, -L3) 321 | interseccion(L1, L2, L3) :- 322 | interseccionAux(L1, L2, [], L3). 323 | 324 | \end{minted} 325 | \end{centrado} 326 | 327 | \paragraph{II.} 328 | \begin{centrado} 329 | \begin{minted}[tabsize=4]{prolog} 330 | sufijoDeLongitud(L, N, S) :- 331 | sufijo(S, L), 332 | length(S, N). 333 | 334 | prefijoDeLongitud(L, N, S) :- 335 | prefijo(S, L), 336 | length(S, N). 337 | 338 | %split(+N,+L, -L1, -L2) -- N y L deben estar definidos 339 | split(N, L, L1, L2) :- 340 | length(L, M), 341 | N1 is M - N, 342 | prefijoDeLongitud(L, N, L1), 343 | sufijoDeLongitud(L, N1, L2). 344 | 345 | \end{minted} 346 | \end{centrado} 347 | 348 | \paragraph{III.} 349 | \begin{centrado} 350 | \begin{minted}[tabsize=4]{prolog} 351 | %borrar(+ListaOriginal, +X, -ListaSinXs) 352 | borrar([], _, []). 353 | borrar([X | T], X, ListaSinXs) :- 354 | borrar(T, X, ListaSinXs). 355 | borrar([ Y | T], X, [ Y | Rec ]) :- 356 | X \= Y, 357 | borrar(T, X, Rec). 358 | \end{minted} 359 | \end{centrado} 360 | \paragraph{IV.} 361 | \begin{centrado} 362 | \begin{minted}[tabsize=4]{prolog} 363 | %sacarDuplicados(+L1, -L2) 364 | sacarDuplicados([], []). 365 | sacarDuplicados([ X | T], [ X | Rec ]) :- 366 | borrar(T, X, T1), 367 | sacarDuplicados(T1, Rec). 368 | \end{minted} 369 | \end{centrado} 370 | \newpage 371 | \paragraph{V.} 372 | \begin{centrado} 373 | \begin{minted}[tabsize=4]{prolog} 374 | %concatenarTodas( +LL, -L) 375 | concatenarTodas([], []). 376 | concatenarTodas([ X | T], Res) :- 377 | concatenarTodas(T, Rec), 378 | concatenar(X, Rec, Res). 379 | 380 | %todosSusMiembrosSonSublitas(+LListas, +L) 381 | todosSusMiembrosSonSublitas([], _). 382 | todosSusMiembrosSonSublitas([ X | XS], L) :- 383 | sublista(X, L), 384 | todosSusMiembrosSonSublitas(XS, L). 385 | %reparto(+L, +N, -LListas) 386 | reparto(L, N, LListas) :- 387 | length(LListas, N), 388 | todosSusMiembrosSonSublitas(LListas, L), 389 | concatenarTodas(LListas, L). 390 | \end{minted} 391 | \end{centrado} 392 | 393 | \paragraph{VI.} 394 | \begin{centrado} 395 | \begin{minted}[tabsize=4]{prolog} 396 | %repartoSinVacias(+L, -LListas) 397 | repartoSinVacias(L, LListas) :- 398 | length(L, N), 399 | between(1, N, X), 400 | reparto(L, X, LListas), 401 | not(member([], LListas)). 402 | \end{minted} 403 | \end{centrado} 404 | 405 | \subsection{Ejercicio 10} 406 | \begin{centrado} 407 | \begin{minted}[tabsize=4]{prolog} 408 | %intercalar(?L1, ?L2, ?L3) -- Funciona para todas las combinaciones posibles. 409 | intercalar([], [], []). 410 | intercalar([], L, L) :- 411 | length(L, N), 412 | N >= 1. 413 | intercalar(L, [], L) :- 414 | length(L, N), 415 | N >= 1. 416 | intercalar([ X | T1], [ Y | T2 ], [ X, Y | T3 ] ) :- 417 | intercalar(T1, T2, T3). 418 | \end{minted} 419 | \end{centrado} 420 | 421 | \subsection{Ejercicio 11} 422 | \begin{centrado} 423 | \begin{minted}[tabsize=4]{prolog} 424 | %arbolEjemplo 425 | arbolEjemplo(bin(bin(nil,1,nil),2,bin(bin(nil,10,nil),20,bin(nil,30,nil)))). 426 | 427 | %vacio(?A) 428 | vacio(nil). 429 | 430 | %raiz(?A, ?R) 431 | raiz(bin(_,X,_), X). 432 | 433 | %altura(+A, -H) 434 | altura(nil, 0). 435 | altura(bin(I, _, D), H) :- 436 | altura(I, HI), 437 | altura(D, HD), 438 | H is max(HI, HD) + 1. 439 | 440 | %cantidadDeNodos(+A, -N) 441 | cantidadDeNodos(nil, 0). 442 | cantidadDeNodos(bin(I, _, D), N) :- 443 | cantidadDeNodos(I, NI), 444 | cantidadDeNodos(D, ND), 445 | N is NI + ND + 1. 446 | \end{minted} 447 | \end{centrado} 448 | 449 | \subsection{Ejercicio 12} 450 | \begin{centrado} 451 | \begin{minted}[tabsize=4]{prolog} 452 | %inorder(+AB, -Lista) 453 | inorder(nil, []). 454 | inorder(bin(I, X, D), Inorder) :- 455 | inorder(I, LI), 456 | inorder(D, LD), 457 | append(LI, [X | LD], Inorder). 458 | 459 | %arbolConInorder(-L, +AB) 460 | arbolConInorder([], nil). 461 | arbolConInorder(XS, bin(AI, X, AD)) :- 462 | reparto(XS, 2, [LI, [X | LD]]), 463 | arbolConInorder(LI, AI), 464 | arbolConInorder(LD, AD). 465 | 466 | %abb(+T) 467 | aBB(nil). 468 | aBB(bin(I, _, D)) :- 469 | aBB(I), 470 | aBB(D). 471 | 472 | %aBBInsertar(+X, +T1, -T2) 473 | aBBInsertar(X, nil, bin(nil, X, nil)). 474 | aBBInsertar(X, bin(AI, Y, AD), bin(AIM, Y, AD)) :- 475 | X =< Y, 476 | aBBInsertar(X, AI, AIM). 477 | aBBInsertar(X, bin(AI, Y, AD), bin(AI, Y, ADM)) :- 478 | X >= Y, 479 | aBBInsertar(X, AD, ADM). 480 | \end{minted} 481 | \end{centrado} 482 | 483 | \section*{Generate and test} 484 | 485 | \subsection{Ejercicio 13} 486 | \begin{centrado} 487 | \begin{minted}[tabsize=4]{prolog} 488 | %coprimos(-X,-Y) 489 | coprimos(X,Y) :- 490 | desde(2, X), 491 | between(2, X, Y), 492 | 1 is gcd(X,Y). 493 | \end{minted} 494 | \end{centrado} 495 | \subsection{Ejercicio 14} 496 | \begin{centrado} 497 | \begin{minted}[tabsize=4]{prolog} 498 | listasQueSuman([],0,0). 499 | listasQueSuman([X|XS],S,N):- 500 | between(0,S,X), 501 | N2 is N-1, 502 | length(XS,N2), 503 | S2 is S-X, 504 | listasQueSuman(XS,S2,N2). 505 | 506 | cuadradoSemiLatinoAux(_,0,[],_). 507 | cuadradoSemiLatinoAux(M,N,[X|XS],S):- 508 | N2 is N-1, 509 | listasQueSuman(X,S,M), 510 | cuadradoSemiLatinoAux(M,N2,XS,S). 511 | 512 | cuadradoSemiLatino(N,XS):- 513 | length(XS,N), 514 | desde(0,S), 515 | cuadradoSemiLatinoAux(N,N,XS,S). 516 | \end{minted} 517 | \end{centrado} 518 | 519 | \subsection{Ejercicio 15} 520 | (Solución dada en clases) 521 | \begin{centrado} 522 | \begin{minted}[tabsize=4]{prolog} 523 | %ladoValido(+A, +B, +C) 524 | ladoValido(A,B,C) :- 525 | S is B+C, 526 | A < S, 527 | D is abs(B-C), 528 | A > D. 529 | 530 | %esTriangulo(+T) 531 | esTriangulo(tri(A,B,C)) :- 532 | ladoValido(A,B,C), 533 | ladoValido(B,C,A), 534 | ladoValido(C,A,B). 535 | 536 | %perim etro(?T,?P) 537 | perimetro(tri(A,B,C), P) :- 538 | desde2(3,P), 539 | M is P-2, 540 | between(1,M,A), 541 | N is P - A -1, 542 | between(1, N, B), 543 | C is P - A - B, 544 | esTriangulo(tri(A,B,C)). 545 | \end{minted} 546 | \end{centrado} 547 | 548 | \section*{\ Negación por falla} 549 | 550 | \subsection{Ejercicio 16} 551 | \begin{centrado} 552 | \begin{minted}[tabsize=4]{prolog} 553 | %diferenciaSimétrica(Lista1, +Lista2, -Lista3) 554 | diferenciaSimetrica([], L2, L2). 555 | diferenciaSimetrica([ X | L1], L2, [ X | XS]) :- 556 | not(member(X, L2)), 557 | diferenciaSimetrica(L1, L2, XS). 558 | diferenciaSimetrica([ X | L1], L2, XS) :- 559 | member(X, L2), 560 | borrar(L2, X, L2SinX), 561 | diferenciaSimetrica(L1, L2SinX, XS). 562 | \end{minted} 563 | \end{centrado} 564 | 565 | \subsection{Ejercicio 17} 566 | \paragraph{I.} La consulta busca todos los valores para los que valga $P(Y)\land \lnot Q(Y)$. 567 | \paragraph{II.} Si se invierten el orden de los literales y queda \prolog{not(q(Y)),p(Y)}, entonces prolog se cuelga porque no puede instanciar \prolog{Y} correctamente. 568 | 569 | \subsection{Ejercicio 18} 570 | \begin{centrado} 571 | \begin{minted}[tabsize=4]{prolog} 572 | %sumList 573 | sumList([], 0). 574 | sumList([X | XS], N) :- 575 | sumList(XS, N1), 576 | N is N1 + X. 577 | 578 | %diff 579 | diff(L1, L2, DL) :- 580 | sumList(L1, N1), 581 | sumList(L2, N2), 582 | DL is abs(N1-N2). 583 | 584 | %corteMásParejo(+L,-L1,-L2) 585 | corteMasParejo(L, L1, L2) :- 586 | append(L1, L2, L), 587 | diff(L1,L2,DL), 588 | not((append(M1,M2,L), 589 | diff(M1,M2,DM), 590 | DM < DL 591 | )). 592 | \end{minted} 593 | \end{centrado} 594 | % 595 | %\subsection{Ejercicio 19} 596 | %\begin{itemize} 597 | %\item 598 | %\end{itemize} 599 | % 600 | % 601 | %\subsection{Ejercicio 20} 602 | %\begin{itemize} 603 | %\item 604 | %\end{itemize} 605 | % 606 | %\subsection{Ejercicio 21} 607 | %\begin{itemize} 608 | %\item 609 | %\end{itemize} 610 | % 611 | %\subsection{Ejercicio 22} 612 | %\begin{itemize} 613 | %\item 614 | %\end{itemize} 615 | % 616 | \end{document} 617 | -------------------------------------------------------------------------------- /practicas_solucion/practica_5.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,a4paper]{article} 2 | \input{header} 3 | 4 | \setcounter{section}{5} 5 | 6 | \begin{document} 7 | \title{PLP - Práctica 5: Programación Orientada a Objetos} 8 | % 9 | \date{\today} 10 | % 11 | \author{Gianfranco Zamboni} 12 | % 13 | \maketitle 14 | \setcounter{page}{1} 15 | % 16 | \section*{Programación en JS} 17 | \subsection{Ejercicio 1} 18 | \begin{multicols}{2} 19 | \paragraph{a)} 20 | \begin{centrado2} 21 | \begin{minted}[breaklines, tabsize=2]{javascript} 22 | c1i = { 23 | r: 1, 24 | i: 1 25 | } 26 | \end{minted} 27 | \end{centrado2} 28 | \paragraph{b)} 29 | \begin{centrado2} 30 | \begin{minted}[breaklines, tabsize=2]{javascript} 31 | c1i.sumar = function(complejo){ 32 | this.r += complejo.r 33 | this.i += complejo.i 34 | } 35 | \end{minted} 36 | \end{centrado2} 37 | \end{multicols} 38 | \begin{multicols}{2} 39 | \paragraph{c)} 40 | \begin{centrado2} 41 | \begin{minted}[breaklines, tabsize=2]{javascript} 42 | c1i.sumar = function(complejo){ 43 | return { 44 | r: this.r + complejo.r 45 | i: this.i + complejo.i 46 | } 47 | } 48 | \end{minted} 49 | \end{centrado2} 50 | 51 | \paragraph{d)} Asi como están implementadas, funciona. 52 | \end{multicols} 53 | \begin{multicols}{2} 54 | 55 | \paragraph{e)} 56 | \begin{centrado2} 57 | \begin{minted}[breaklines, tabsize=2]{javascript} 58 | let c = c1i.sumar(c1i) 59 | 60 | c.restar = function(complejo){ 61 | return { 62 | r: this.r - complejo.r 63 | i: this.i - complejo.i 64 | } 65 | } 66 | \end{minted} 67 | \end{centrado2} 68 | \texttt{c1i} no tiene definida la función restar, por lo que \texttt{c1i.restar(\_)} nos dará un error. 69 | \vfill\null 70 | \columnbreak 71 | \paragraph{f)} 72 | \begin{minted}[breaklines, tabsize=2]{javascript} 73 | c1i.mostrar = function () { 74 | if(this.i != 1){ 75 | console.log( 76 | `${this.r} + ${this.i}i`); 77 | }else{ 78 | console.log(`${this.r} + i"); 79 | } 80 | } 81 | \end{minted} 82 | 83 | En este caso, \texttt{c} no podrá mostrar sus elementos, ya que cuando lo creamos lo hacemos como un objeto nuevo que no está relacionado con \texttt{c}. 84 | 85 | \end{multicols} 86 | 87 | \newpage 88 | \subsection{Ejercicio 2} 89 | 90 | \begin{multicols}{2} 91 | \begin{centrado2} 92 | \begin{minted}[breaklines, tabsize=2]{javascript} 93 | 94 | // a) 95 | let t = {} 96 | 97 | t.ite = function(a,b) { 98 | return a; 99 | } 100 | 101 | // b) 102 | t.mostrar = function() { 103 | return "Verdadero"; 104 | } 105 | 106 | // c) 107 | t.not = function(){ 108 | return f; 109 | } 110 | 111 | t.and = function(otroValor) { 112 | return otroValor; 113 | } 114 | 115 | \end{minted} 116 | \end{centrado2} 117 | \begin{centrado2} 118 | \begin{minted}[breaklines, tabsize=2]{javascript} 119 | 120 | // a) 121 | let f = {} 122 | 123 | f.ite = function(a,b) { 124 | return b; 125 | } 126 | 127 | // b) 128 | f.mostrar = function(){ 129 | return "Falso"; 130 | } 131 | 132 | // c) 133 | f.not = function(){ 134 | return t; 135 | } 136 | 137 | f.and = function(element) { 138 | return this; 139 | } 140 | 141 | \end{minted} 142 | \end{centrado2} 143 | \end{multicols} 144 | 145 | \subsection{Ejercicio 3} 146 | \begin{centrado} 147 | \begin{minted}[breaklines, tabsize=2]{javascript} 148 | // a) 149 | let Cero = {}; 150 | 151 | Cero.esCero = function(){ 152 | return true; 153 | }; 154 | 155 | Cero.succ = function(){ 156 | return new Sucesor(this); 157 | } 158 | 159 | 160 | function Sucesor(pred){ 161 | this.predecesor = pred; 162 | }; 163 | 164 | Sucesor.prototype.__proto__ = Cero; 165 | 166 | Sucesor.prototype.pred = function(){ 167 | return this.predecesor; 168 | } 169 | 170 | // b) 171 | Cero.toNumber = function(){ 172 | return 0; 173 | } 174 | 175 | Sucesor.prototype.toNumber = function(){ 176 | return this.pred().toNumber() + 1; 177 | } 178 | 179 | // c) 180 | Cero.for = function(f){} 181 | 182 | Sucesor.prototype.for = function(f){ 183 | this.pred().for(f); 184 | f.eval(this); 185 | } 186 | \end{minted} 187 | \end{centrado} 188 | 189 | \newpage 190 | \subsection{Ejercicio 4} 191 | \paragraph{a)} 192 | \begin{centrado} 193 | \begin{minted}[breaklines, tabsize=2]{javascript} 194 | var Punto = {}; 195 | Punto.new = function(x,y) { 196 | var p = {}; 197 | p.x=x; 198 | p.y=y; 199 | p.mostrar = function () { 200 | return Punto.mostrar(this); 201 | } 202 | return p; 203 | } 204 | 205 | Punto.mostrar = function(o) { 206 | return `Punto(${o.x},${o.y})` 207 | } 208 | 209 | \end{minted} 210 | \end{centrado} 211 | \paragraph{b)} 212 | \begin{centrado} 213 | \begin{minted}[breaklines, tabsize=2]{javascript} 214 | var PuntoColoreado = {}; 215 | PuntoColoreado.new = function(x,y){ 216 | var p = Punto.new(x,y); 217 | p.color = "rojo"; 218 | p.mostrar = function(){ 219 | return PuntoColoreado.mostrar(this); 220 | }; 221 | return p; 222 | }; 223 | 224 | PuntoColoreado.mostrar = function(o) { 225 | return Punto.mostrar(o); 226 | }; 227 | \end{minted} 228 | \end{centrado} 229 | 230 | \paragraph{c)} 231 | \begin{centrado} 232 | \begin{minted}[breaklines, tabsize=2]{javascript} 233 | var PuntoColoreado = {}; 234 | PuntoColoreado.cons = function (x,y,color) { 235 | var nuevo = this.new(x,y); 236 | nuevo.color = color; 237 | return nuevo; 238 | } 239 | \end{minted} 240 | \end{centrado} 241 | 242 | \paragraph{\red{d)}} 243 | %\begin{centrado} 244 | %\begin{minted}[breaklines, tabsize=2]{javascript} 245 | %\begin{lstlisting} 246 | % var p1 = Punto.neww(1 ,2); 247 | % var pc1 = PuntoColoreado.neww(1 ,2); 248 | % Punto.mover = "me muevo"; 249 | % var p2 = Punto.neww(1 ,2); 250 | % var pc2 = PuntoColoreado.neww(1 ,2); 251 | % 252 | % console.log(p1.mover); 253 | % console.log(pc1.mover); 254 | % console.log(p2.mover); 255 | % console.log(pc2.mover); 256 | % 257 | % // Se pude observar que todos los objetos se pueden mover, porque los puntos coloreados tienen una referencia a los puntos, por lo tanto si se agrga una funcionalidad al punto, tanbién se agregará al punto coloreado. 258 | %\end{minted} 259 | %\end{centrado} 260 | % 261 | \subsection{Ejercicio 5} 262 | \begin{centrado} 263 | \begin{minted}[breaklines, tabsize=2]{javascript} 264 | function Punto(x, y){ 265 | this.x = x; 266 | this.y = y; 267 | } 268 | 269 | Punto.prototype.mostrar = function(){ 270 | return `Punto(${this.x},${this.y})` 271 | } 272 | 273 | function PuntoColoreado(x,y, color) { 274 | this.x = x 275 | this.y = y 276 | this.color = color 277 | } 278 | PuntoColoreado.prototype.__proto__ = Punto.prototype 279 | 280 | Punto.prototype.moverX = function(x){ 281 | this.x += x 282 | } 283 | \end{minted} 284 | \end{centrado} 285 | 286 | \subsection{Ejercicio 6} 287 | \paragraph{a)} En el primer caso, una vez creado el objeto a, el prototipo de este objeto ya queda fijo. Cuando realizamos la asignación \mintinline{javascript}{C1.prototype = C2.prototype;}, la variable \texttt{C1.prototype} deje de referenciar al objeto prototipo de \texttt{a} y referencie al objeto que referencia \texttt{C2.prototype}. Provocando, esto, que el constructor \mintinline{javascript}{C1()} lo asigne como prototipo de \texttt{b}. 288 | 289 | Entonces \texttt{a} sigue teniendo el mismo prototipo y \texttt{b} tiene como prototipo a \texttt{C2} por lo que los resultados de evaluar sus atributos son: 290 | 291 | \begin{centrado} 292 | \begin{minted}[breaklines, tabsize=2]{javascript} 293 | a.g // 'Hola' 294 | b.g // 'Mundo' 295 | \end{minted} 296 | \end{centrado} 297 | 298 | \paragraph{b)} En el segundo caso, estamos modificando el atributo \texttt{g} del objeto que es referenciado por \\ \texttt{C1.prototype}. La asignación \mintinline{javascript}{C1.prototype.g = C2.prototype.g;} remplaza la función \texttt{g} original de \texttt{C1.prototype} por la función \texttt{g} de \texttt{C2.prototype}. 299 | Entonces, las soluciones quedan: 300 | 301 | \begin{centrado} 302 | \begin{minted}[breaklines]{javascript} 303 | a.g // 'Mundo' 304 | b.g // 'Mundo' 305 | \end{minted} 306 | \end{centrado} 307 | 308 | \subsection{Ejercicio 7} 309 | \paragraph{a)} \texttt{a} será un array con todas las claves de \texttt{o1} y \texttt{b} será el array con todos sus valores en el mismo orden, es decir, si en \texttt{a[0]} se encuentra la clave \mintinline{javascript}{'a'}, entonces en \texttt{b[0}] se encuentra el valor \mintinline{javascript}{1}. 310 | 311 | \paragraph{b)} 312 | \begin{centrado} 313 | \begin{minted}[breaklines, tabsize=2]{javascript} 314 | function extender(o1, o2) { 315 | for(let key in o1) { 316 | if(o2[key] == undefined){ 317 | o2[key] = o1[key]; 318 | } 319 | } 320 | } 321 | \end{minted} 322 | \end{centrado} 323 | 324 | \paragraph{c)} Hay que hacer dos modificaciones: Definir en \texttt{B} el método y eliminarlo de A. 325 | \begin{centrado} 326 | \begin{minted}[breaklines, tabsize=2]{javascript} 327 | B.presentar = A.presentar 328 | delete A.presentar 329 | \end{minted} 330 | \end{centrado} 331 | 332 | \paragraph{d)} Es lo mismo que en el anterior, pero usando \texttt{prototype}. 333 | \begin{centrado} 334 | \begin{minted}[breaklines, tabsize=2]{javascript} 335 | B7d.prototype.presentar = A7d.prototype.presentar 336 | delete A7d.prototype.presentar 337 | \end{minted} 338 | \end{centrado} 339 | 340 | \section*{Cálculo de Objetos} 341 | 342 | \subsection{Ejercicio 8} 343 | \paragraph{a)} Ambos objetos tienen tienen los mismos atributos y los métodos asociados a cada tributo son equivalentes (son los mismos, salvo renombre de variables). 344 | \paragraph{b)} En este caso, los objetos tienen distintas etiquetas por lo que no pueden ser considerados iguales. 345 | Representan a distintos objetos porque responden a los distintos mensajes. 346 | \subsection{Ejercicio 9} 347 | \paragraph{a)} 348 | \vspace*{5mm} 349 | \begin{center} 350 | \begin{scprooftree} 351 | \def\extraVskip{5pt} 352 | 353 | \AxiomC{} 354 | \RightLabel{[Obj]} 355 | \UnaryInfC{$o \longTo o$} 356 | 357 | \AxiomC{} 358 | \RightLabel{[Obj]} 359 | \UnaryInfC{$o \longTo o$} 360 | 361 | \AxiomC{} 362 | \RightLabel{[Obj]} 363 | \UnaryInfC{$(x)\{x \leftarrow o\} \longTo o$} 364 | 365 | \RightLabel{[Sel]} 366 | \BinaryInfC{$(x.arg)\{x \leftarrow o\} \longTo o$} 367 | 368 | \RightLabel{[Sel]} 369 | \BinaryInfC{$o.val \longTo o$} 370 | \end{scprooftree} 371 | \end{center} 372 | \paragraph{b)} 373 | \vspace*{5mm} 374 | \begin{center} 375 | \begin{scprooftree} 376 | \def\extraVskip{5pt} 377 | \AxiomC{Por 9.a)} 378 | \UnaryInfC{$o.val \longTo o$} 379 | \AxiomC{} 380 | \RightLabel{[Obj]} 381 | \UnaryInfC{$o \longTo o$} 382 | \RightLabel{[Obj]} 383 | \UnaryInfC{$o.val \longTo o$} 384 | \AxiomC{} 385 | \RightLabel{[Obj]} 386 | \UnaryInfC{$o \longTo o$} 387 | 388 | 389 | \AxiomC{$(x)\{x \leftarrow o\} \longTo o$} 390 | \RightLabel{[Sel]} 391 | \BinaryInfC{$(x.arg)\{x \leftarrow o\} \longTo o$} 392 | \RightLabel{[Sel]} 393 | \BinaryInfC{$(x)\{x \leftarrow o\} \longTo o$} 394 | \RightLabel{[Sel]} 395 | \BinaryInfC{$o.val.arg \longTo o$} 396 | \end{scprooftree} 397 | \end{center} 398 | 399 | \paragraph{c)} 400 | \vspace*{5mm} 401 | \begin{center}\small 402 | \begin{scprooftree} 403 | \def\extraVskip{5pt} 404 | \AxiomC{} 405 | \RightLabel{[Obj]} 406 | \UnaryInfC{$\OOReduccion{o}{o}$} 407 | \RightLabel{[Upd]} 408 | \UnaryInfC{$\OOReduccion{\OORedefinicion{o.arg}{\OOMetodo{z}{0}}}{o'}$} 409 | 410 | \AxiomC{$o'\equiv [\OOAtributo{arg}{z}{0}, \OOAtributo{val}{x}{x.arg}]$} 411 | 412 | \AxiomC{$\OOReduccion{o'}{o'}$} 413 | \AxiomC{$\OOReduccion{0\{x\leftarrow o'\}}{0}$} 414 | \RightLabel{[Sel]} 415 | \BinaryInfC{$\OOReduccion{x.arg\{x\leftarrow o'\}}{0}$} 416 | \RightLabel{[Sel]} 417 | \TrinaryInfC{$\OOReduccion{(\OORedefinicion{o.arg}{\OOMetodo{z}{0}}).val}{0}$} 418 | \end{scprooftree} 419 | \end{center} 420 | 421 | \newpage 422 | \subsection{Ejercicio 10} 423 | \vspace*{5mm} 424 | \begin{center} 425 | \begin{scprooftree} 426 | \def\extraVskip{5pt} 427 | 428 | \AxiomC{(1)} 429 | \UnaryInfC{$\OOReduccion{o.a}{o'}$} 430 | \AxiomC{$o' \equiv [\OOAtributo{a}{y}{y := [~]}]$} 431 | 432 | \AxiomC{$\OOReduccion{o'}{o'}$} 433 | \RightLabel{[Upd]} 434 | \UnaryInfC{$\OOReduccion{(y.a :=[~])\{y\leftarrow o'\}}{[a = [~]~]}$} 435 | \RightLabel{[Sel]} 436 | \TrinaryInfC{$\OOReduccion{o.a.a}{[a = [~]~]}$} 437 | \end{scprooftree} 438 | \end{center} 439 | \vspace{5mm} 440 | \begin{center}\textbf{(1)} 441 | \begin{scprooftree} 442 | \def\extraVskip{5pt} 443 | 444 | \AxiomC{$\OOReduccion{o}{o}$} 445 | 446 | \AxiomC{$\OOReduccion{o}{o}$} 447 | \RightLabel{[Upd]} 448 | \UnaryInfC{$(\OOReduccion{\OORedefinicion{x.a}{\OOMetodo{y}{(y := [~])})\{x\leftarrow o\}}}{[\OOAtributo{a}{y}{y := [~]}]}$} 449 | \RightLabel{[Sel]} 450 | \BinaryInfC{$\OOReduccion{o.a}{[\OOAtributo{a}{y}{y := [~]}]}$} 451 | \end{scprooftree} 452 | \end{center} 453 | \subsection{Ejercicio 11} 454 | \paragraph{a)} 455 | \setlength{\columnsep}{-5cm} 456 | \begin{multicols}{2} 457 | \begin{align*} 458 | true = [~¬ = false, \\ 459 | &if = \lambda(y)\lambda(z)y, \\ 460 | &ifnot = \lambda(y)\lambda(z)f.if(y,z) \\ 461 | ]~& \\ 462 | \end{align*} 463 | 464 | \begin{align*} 465 | false = [~¬ = true, \\ 466 | &if = \lambda(y)\lambda(z)z, \\ 467 | &ifnot = \lambda(y)\lambda(z)t.if(y,z) \\ 468 | ]~& \\ 469 | \end{align*} 470 | \end{multicols} 471 | 472 | \paragraph{b)} 473 | \begin{multicols}{2} 474 | \begin{align*} 475 | true = [~¬ = false, \\ 476 | &if = \lambda(y)\lambda(z)y, \\ 477 | ]~& \\ 478 | \end{align*} 479 | 480 | \begin{align*} 481 | false = [~¬ = true, \\ 482 | &if = \lambda(y)\lambda(z)z, \\ 483 | ]~& \\ 484 | \end{align*} 485 | \end{multicols} 486 | \setlength{\columnsep}{5mm} 487 | \subsection{Ejercicio 12} 488 | \paragraph{a)} 489 | \begin{align*} 490 | origen \equalDef [~& x = 0, \\ 491 | & y = 0, \\ 492 | & \OOAtributo{mv}{p}{\lambda(w)\lambda(z) (p.x:=p.x+w).y:=p.y+z} 493 | ]~& \\ 494 | \end{align*} 495 | \paragraph{b)} 496 | \begin{align*} 497 | Punto \equalDef [~& \OOAtributo{new}{z}{[~x= z.x,~y = z.y,~ \OOAtributo{mv}{c}{\lambda(x_1)\lambda(x_2) z.mv(c,x_1,x_2)}] 498 | }, \\ 499 | & x = \lambda(p)0, \\ 500 | & y = \lambda(p)0, \\ 501 | & \OOAtributo{mv}{c}{\lambda(p)\lambda(w)\lambda(z) (p.x:=p.x+w).y:=p.y+z} ] \\ 502 | \end{align*} 503 | 504 | \paragraph{c)} 505 | \vspace{5mm} 506 | \begin{center}\small 507 | \begin{scprooftree} 508 | \def\extraVskip{5pt} 509 | 510 | \AxiomC{$\OOReduccion{Punto}{Punto}$} 511 | 512 | \AxiomC{$\OOReduccion{[~x=z.x,~y = z.y,~ \OOAtributo{mv}{p}{\lambda(x_1)\lambda(x_2) z.mv(p,x_1,x_2)}]\{z\leftarrow Punto\}}{p}$} 513 | \RightLabel{[Sel]} 514 | \BinaryInfC{$\OOReduccion{Punto.new}{p}$} 515 | \end{scprooftree} 516 | \end{center} 517 | con $p \equalDef [~x=Punto.x,~y = Punto.y,~ \OOAtributo{mv}{p}{\lambda(x_1)\lambda(x_2) Punto.mv(p,x_1,x_2)}]$ 518 | 519 | \paragraph{d)} 520 | \begin{align*} 521 | PuntoColoreado \equalDef [~& \OOAtributo{new}{z}{[~x=z.x,~y = z.y,~color=z.color, \OOAtributo{mv}{p}{\lambda(x_1)\lambda(x_2) z.mv(p,x_1,x_2)}] 522 | }, \\ 523 | & x = \lambda(p)Punto.x, \\ 524 | & y = \lambda(p)Punto.y, \\ 525 | & color = \lambda(p)\text{``rojo''}, \\ 526 | & mv = Punto.mv ] \\ 527 | \end{align*} 528 | 529 | \subsection{Ejercicio 13} 530 | \paragraph{a)} 531 | \begin{align*} 532 | plantaClass = [~& \OOAtributo{new}{c}{[altura = c.altura,~\OOAtributo{crecer}{t}c.crecer~t]}, \\ 533 | &altura = 10,\\ 534 | &\OOAtributo{crecer}{c}{\lambda(t)t.altura := (t.altura + 10)} \\ 535 | ]~&\\ 536 | \end{align*} 537 | 538 | \paragraph{b)} 539 | \vspace{5mm} 540 | \begin{center} 541 | \begin{scprooftree} 542 | \def\extraVskip{5pt} 543 | 544 | \AxiomC{(1)} 545 | \UnaryInfC{$\OOReduccion{{plantaClass.new}}{p'}$} 546 | \AxiomC{$\OOReduccion{(plantaClass.crecer~t)\{t\leftarrow p'\}}{p}$} 547 | \RightLabel{[Sel]} 548 | \BinaryInfC{$\OOReduccion{plantaClass.new.crecer}{[altura = 20,~\OOAtributo{crecer}{t}plantaClass.crecer~t]}$} 549 | \end{scprooftree} 550 | \end{center} 551 | 552 | con $p \equiv [altura = 20,~\OOAtributo{crecer}{t}plantaClass.crecer~t]$ 553 | 554 | \vspace{5mm} 555 | \begin{center}\textbf{(1)}\small 556 | \begin{scprooftree} 557 | \def\extraVskip{5pt} 558 | 559 | \AxiomC{} 560 | \RightLabel{[Obj]} 561 | \UnaryInfC{$\OOReduccion{plantaClass}{plantaClass}$} 562 | 563 | \AxiomC{$\OOReduccion{[altura = c.altura,~\OOAtributo{crecer}{t}c.crecer~t]\{c\leftarrow plantaClass\}}{p'}$} 564 | \RightLabel{[Sel]} 565 | \BinaryInfC{$\OOReduccion{{plantaClass.new}}{p'}$} 566 | \end{scprooftree} 567 | \end{center} 568 | con $p' \equiv [altura = plantaClass.altura,~\OOAtributo{crecer}{t}plantaClass.crecer~t]$ 569 | 570 | \paragraph{c)} 571 | \begin{align*} 572 | broteClass = [~& \OOAtributo{new}{c}{[altura = c.altura,~\OOAtributo{crecer}{t}c.crecer~t]}, \\ 573 | &altura = 1,\\ 574 | &crecer = \lambda(t)plantaClass.crecer~t \\ 575 | ]~&\\ 576 | \end{align*} 577 | 578 | \paragraph{d)} 579 | \begin{align*} 580 | malezaClass = [~& \OOAtributo{new}{c}{[altura = c.altura,~\OOAtributo{crecer}{t}c.crecer~t]}, \\ 581 | &altura = plantaClass.altura,\\ 582 | &crecer = \lambda(t)t.altura := (t.altura *2) \\ 583 | ]~&\\ 584 | \end{align*} 585 | 586 | \paragraph{e)} 587 | \begin{align*} 588 | frutalClass = [~& \OOAtributo{new}{c}{[altura = c.altura,~cantFrutos = c.cantFrutos,~\OOAtributo{crecer}{t}c.crecer~t]}, \\ 589 | &cantFrutos = 0, \\ 590 | &altura = plantaClass.altura,\\ 591 | &crecer = \lambda(t)((plantaClass.crecer t).cantFrutos := t.cantFrutos+1) \\ 592 | ]~&\\ 593 | \end{align*} 594 | 595 | \paragraph{f)} 596 | \begin{align*} 597 | frutalMixin = \lambda(m)[~& \OOAtributo{new}{c}{[altura = c.altura,~cantFrutos = frutalMixin(m).cantFrutos,~\\ 598 | &\qquad\qquad\qquad \OOAtributo{crecer}{t}frutalMixin(m).crecer(t)]}, \\ 599 | &cantFrutos = 0, \\ 600 | &crecer = \lambda(t)((m.crecer(t)).cantFrutos := t.cantFrutos+1) \\ 601 | ]~&\\ 602 | \end{align*} 603 | \end{document} 604 | 605 | 606 | -------------------------------------------------------------------------------- /apuntes/secciones/apendices.tex: -------------------------------------------------------------------------------- 1 | \part{Apéndices} 2 | 3 | 4 | \section{Programación funcional en Haskell} 5 | \paragraph{Tipos elementales} 6 | \begin{centrado} 7 | \begin{minted}{haskell} 8 | 1 -- Int Enteros 9 | 'a' -- Char Caracteres 10 | 1.2 -- Float Números de punto flotante 11 | True -- Bool Booleanos 12 | [1,2,3] -- [Int] Listas 13 | (1, True) -- (Int, Bool) Tuplas, pares 14 | length -- [a] -> Int Funciones 15 | length [1,2,3] -- Int Expresiones 16 | \x -> x -- a -> a Funciones anónimas 17 | \end{minted} 18 | \end{centrado} 19 | 20 | \paragraph{Guardas} 21 | \begin{centrado} 22 | \begin{minted}{haskell} 23 | signo n | n >= 0 = True 24 | | otherwise = False 25 | \end{minted} 26 | \end{centrado} 27 | 28 | \paragraph{Pattern Matching} 29 | \begin{centrado} 30 | \begin{minted}{haskell} 31 | longitud [] = 0 32 | longitud (x:xs) = 1 + (longitud xs) 33 | \end{minted} 34 | \end{centrado} 35 | 36 | \paragraph{Polimorfismo paramétrico} 37 | \begin{centrado} 38 | \begin{minted}{haskell} 39 | todosIguales :: Eq a => [a] -> Bool 40 | todosIguales [] = True 41 | todosIguales [x] = True 42 | todosIguales (x:y:xs) = x == y && todosIguales(y:xs) 43 | \end{minted} 44 | \end{centrado} 45 | 46 | \paragraph{Clases de tipo} 47 | \begin{centrado} 48 | \begin{minted}{haskell} 49 | Eq a -- Tipos con comparación de igualdad 50 | Num a -- Tipos que se comportan como los números 51 | Ord a -- Tipos orden 52 | Show a -- Tipos que pueden ser representados como strings 53 | \end{minted} 54 | \end{centrado} 55 | 56 | \paragraph{Definición de listas} 57 | \begin{centrado} 58 | \begin{minted}[breaklines]{haskell} 59 | [1,2,3,4,5] -- Por extensión 60 | [1 .. 4] -- Secuencias aritméticas 61 | [ x | x <- [1..], esPar x ] -- Por compresión 62 | 63 | cuando las usamos. Ejemplo de lista infinita: 64 | 65 | infinitosUnos :: [Int] 66 | infinitosUnos = 1 : infinitosUnos 67 | 68 | puntosDelCuadrante :: [(Int, Int)] 69 | puntosDelCuadrante = [ (x, s-x) | s <- [0..], x <-[0..s] ] 70 | \end{minted} 71 | \end{centrado} 72 | 73 | \paragraph{Funciones de alto orden} 74 | \begin{centrado} 75 | \begin{minted}[breaklines]{haskell} 76 | mejorSegun :: (a -> a -> Bool) -> [a] -> a 77 | mejorSegun _ [x] = x 78 | mejorSegun f (x : xs) | f x (mejorSegun f xs) = x 79 | | otherwise = mejorSegun f xs 80 | \end{minted} 81 | \end{centrado} 82 | 83 | \subsection{Otros tipos útiles} 84 | \paragraph{Formula} 85 | \begin{centrado} 86 | \begin{minted}[breaklines]{haskell} 87 | data Formula = Proposicion String | No Formula 88 | | Y Formula Formula 89 | | O Formula Formula 90 | | Imp Formula Formula 91 | 92 | foldFormula :: (String -> a) -> (Formula -> a) -> 93 | (Formula -> Formula -> a) -> (Formula -> Formula -> a) 94 | -> (Formula -> Formula -> a) -> Formula -> a 95 | foldFormula fp fn fy fo fImp form = case form of : 96 | Proposicion s -> fp s 97 | No sf -> fn (rec sf) 98 | Y sf1 sf2 -> fy (rec sf1) (rec sf2) 99 | O sf1 sf2 -> fo (rec sf1) (rec sf2) 100 | Impl sf1 sf2 -> fImpl (rec sf1) (rec sf2) 101 | where rec = foldForm fp fn fy fo fImp 102 | \end{minted} 103 | \end{centrado} 104 | 105 | \paragraph{Rosetree} 106 | \begin{centrado} 107 | \begin{minted}[breaklines]{haskell} 108 | data Rosetree = Rose a [Rosetree] 109 | -- Hay varias formas de definir el fold para esta estructura 110 | foldRose :: (a -> [b] -> b) -> Rosetree a -> b 111 | foldRose f ( Rose x l ) = f x ( map ( foldRose f ) l ) 112 | 113 | foldRose2 :: ( a -> c -> b) -> ( b -> c -> c ) -> c 114 | -> Rosetree a -> b 115 | foldRose2 g f z (Rose x l) = 116 | g x ( foldr f z ( map ( foldRose g f z ) l ) ) 117 | 118 | \end{minted} 119 | \end{centrado} 120 | 121 | 122 | \newpage 123 | \section{Extensiones del lenguaje \texorpdfstring{\(\lambda^b\)}{lambda b}} 124 | 125 | 126 | 127 | \subsection{Registros \texorpdfstring{\(\lambda^{...r}\)}{lambda ...r}} 128 | 129 | \paragraph{Tipos} 130 | \[\sigma, \tau ~::=~...~|~\{l_i : \sigma_i ~^{i\in 1..n}\}\] 131 | 132 | El tipo \(\{l_i : \sigma_i^{i\in 1..n}\}\) representan las estructuras con \(n\) atributos tipados, por ejemplo: \(\{nombre : String,edad:Nat\}\) 133 | \paragraph{Términos} 134 | \[ M~::=~ \dots~|~\{l_i = M_i ~^{i\in 1..n}\}~|~M.l \] 135 | 136 | Los términos significan: 137 | \begin{itemize} 138 | \item El registro \(\{l_i = M_i ~^{i\in 1..n}\}\) evalua \(\{l_i = V_i ~^{i\in 1..n}\}\) donde \(V_i\) es el s al que evalúa \(M_i\) para \(i\in 1..n\). 139 | \item \(M.l\): Proyecta el valor de la etiqueta \(l\) del registro \(M\) 140 | \end{itemize} 141 | 142 | \paragraph{Axiomas y reglas de tipado} 143 | \begin{equation*} 144 | \frac{\judgeType{\Gamma}{M_i}{\sigma_i} \text{ para cada } i \in 1..n}{\judgeType{\Gamma}{\{l_i = M_i ~^{i\in 1..n}\}}{\{l_i : \sigma_i ~^{i\in 1..n}\}}}(\text{T-RCD}) 145 | \end{equation*} 146 | \vspace*{5mm} 147 | \begin{equation*} 148 | \frac{\judgeType{\Gamma}{\{l_i = M_i ~^{i\in 1..n}\}}{\{l_i : \sigma_i ~^{i\in 1..n}\}}\hspace*{5mm} j \in 1..n} 149 | {\judgeType{\Gamma}{M.l_j}{\sigma_j}}(\text{T-Proj}) 150 | \end{equation*} 151 | 152 | \paragraph{Axiomas y reglas de subtipado} 153 | %\begin{equation*} 154 | % \frac{}{\{l_i : \sigma_i~|~i\in 1..n+k\} <: \{l_i : \sigma_i~|~i\in 1..n\}}(\text{S-RcdWidth}) 155 | %\end{equation*} 156 | % 157 | %\vspace*{5mm} 158 | %\begin{equation*} 159 | % \frac{\sigma_i <: \tau_i\hspace*{5mm} i\in I = \{1..n\}}{\{l_i : \sigma_i\}_{i\in I} <: \{l_i : \tau_i\}_{i\in I}}(\text{S-RcdDepth}) 160 | %\end{equation*} 161 | 162 | \begin{equation*} 163 | \frac{\{l_i| i\in 1..n\}\subseteq\{k_j|j\in 1..m\} \hspace*{5mm} k_j = l_i\Rightarrow \sigma_j <: \tau_i}{\{k_j:\sigma_j|j\in 1..m\} <: \{l_i:\sigma_i| i\in 1..n\}}(\text{S-Rcd}) 164 | \end{equation*} 165 | 166 | \vspace*{5mm} 167 | Esta regla nos dice que un registro \(N\) es subtipo de otro registro \(M\), si el conjunto de etiquetas de \(M\) está contenido en el conjunto de etiquetas de \(N\) y, además, si los tipos de cada una de esas etiquetas, en \(M\), es más general que en \(N\). 168 | 169 | Una de las consecuancias de esta regla es que \(\sigma <\{\}\) para todo tipo registro \(\sigma\). Esto es porque \(\{\}\) no tiene etiquetas, osea que su conjunto de etiquetas es el conjunto \(\emptyset\) que está contenido en todos los conjuntos. 170 | \paragraph{Valores} 171 | \[V~::=~\dots~|~\{l_i = V_i ~^{i\in 1..n}\}\] 172 | 173 | 174 | \paragraph{Axiomas y reglas de evaluación} 175 | 176 | \begin{equation*} 177 | \frac{j\in 1..n}{\{l_i = \lambdaValue{V_i} ~^{i\in 1..n}\}.l_j \to \lambdaValue{V_j}}(\text{E-ProjRcd}) 178 | \end{equation*} 179 | \vspace*{5mm} 180 | \begin{equation*} 181 | \frac{M \to M'}{M.l \to M'.l}(\text{E-Proj}) 182 | \end{equation*} 183 | 184 | \vspace*{5mm} 185 | \begin{equation*} 186 | \frac{M_j\to M_j'}{\{l_i = \lambdaValue{V_i}~^{i\in 1..j-1}, l_j = M_j, l_i = M_i ~^{i\in j+1..n}\} \to \{l_i = \lambdaValue{V_i}~^{i\in 1..j-1}, l_j = M'_j, l_i = M_i ~^{i\in j+1..n}\}}(\text{E-RCD}) 187 | \end{equation*} 188 | \vspace*{5mm} 189 | \subsection{Declaraciones Locales (\texorpdfstring{\(\lambda^{...let}\)}{lambda ...let})}\label{extension_lambda:let} 190 | 191 | Con esta extensión, agregamos al lenguaje el término \(\lambdaLet{x}{\sigma}{M}{N}\), que evalúa \(M\) a un valor, liga \(x\) a \(V\) y, luego, evalúa \(N\). Este término solo mejora la legibilidad de los programas que ya podemos definir con el lenguaje hasta ahora definido. 192 | 193 | \paragraph{Términos} 194 | \[ M~::=~ \dots~|~\lambdaLet{x}{\sigma}{M}{N} \] 195 | 196 | 197 | \paragraph{Axiomas y reglas de tipado} 198 | \begin{equation*} 199 | \frac{\judgeType{\Gamma}{M}{\sigma_1}\hspace*{5mm}\judgeType{\Gamma,x:\sigma_1}{N}{\sigma_2}}{\judgeType{\Gamma}{\lambdaLet{x}{\sigma_1}{M}{N}}{\sigma_2}}(\text{T-Let}) 200 | \end{equation*} 201 | 202 | \paragraph{Axiomas y reglas de evaluación} 203 | 204 | \begin{equation*} 205 | \frac{M_1\to M_1'}{\lambdaLet{x}{\sigma}{M_1}{M_2}\to \lambdaLet{x}{\sigma}{M'_1}{M_2}}(\text{E-Let}) 206 | \end{equation*} 207 | \vspace*{5mm} 208 | \begin{equation*} 209 | \frac{}{\lambdaLet{x}{\sigma}{\lambdaValue{V_1}}{M_2}\to \replaceBy{M_2}{x}{\lambdaValue{V_1}}}(\text{E-LetV}) 210 | \end{equation*} 211 | 212 | \subsubsection{Construcción \texorpdfstring{\textit{let}}{let} recursivo (Letrec)} 213 | Una construcción alternativa para definir funciones recursivas es 214 | \[letrec~f:\sigma\to\sigma = \lambdaAbs{x}{\sigma}{M~in~N}\] 215 | 216 | Y \(letRec\) se puede definir en base a \(let\) y \(fix\) (definido en \ref{lambda_calculo:recursion}) de la siguiente forma: 217 | 218 | \[\lambdaLet{f}{\sigma\to\sigma}{(\lambdaFix{\lambdaAbs{f}{\sigma\to\sigma}{\lambdaAbs{x}{\sigma}{M}}})}{N}\] 219 | 220 | \subsection{Tuplas} 221 | 222 | \paragraph{Tipos} 223 | \[\sigma,\tau~::= \dots~|~\sigma\times\tau\] 224 | 225 | \paragraph{Términos} 226 | \[M,~N~::=~\dots~|~~|~\pi_1(M)~|~\pi_2(M)\] 227 | \paragraph{Axiomas y reglas de tipado} 228 | \begin{equation*} 229 | \frac{\judgeType{\Gamma}{M}{\sigma}\hspace*{5mm}\judgeType{\Gamma}{N}{\tau}}{\judgeType{\Gamma}{}{\sigma\times\tau}}(\text{T-Tupla}) 230 | \end{equation*} 231 | \vspace*{5mm} 232 | \begin{equation*} 233 | \frac{\judgeType{\Gamma}{M}{\sigma\times\tau}}{\judgeType{\Gamma}{\pi_1(M)}{\sigma}}(\text{T-}\pi_1)\hspace*{1cm}\frac{\judgeType{\Gamma}{M}{\sigma\times\tau}}{\judgeType{\Gamma}{\pi_2(M)}{\tau}}(\text{T-}\pi_2) 234 | \end{equation*} 235 | 236 | \paragraph{Valores} 237 | \[V~::=~\dots~|~\] 238 | 239 | \paragraph{Axiomas y reglas de evaluación} 240 | \[ 241 | \frac{M\to M'}{\to}(\text{E-Tuplas})\hspace*{1cm}\frac{N\to N'}{<\lambdaValue{V},N>\to<\lambdaValue{V},N'>}(\text{E-Tuplas1}) 242 | \] 243 | \vspace*{5mm} 244 | \begin{equation*} 245 | \frac{M\to M'}{\pi_1(M)\to\pi_1(M')}(\text{E-}\pi_1)\hspace*{1cm}\frac{}{\pi_1(<\lambdaValue{V_1}, \lambdaValue{V_2}>)\to\lambdaValue{V_1}}(\text{E-}\pi'_1) 246 | \end{equation*} 247 | \vspace*{5mm} 248 | \begin{equation*} 249 | \frac{M\to M'}{\pi_2(M)\to\pi_2(M')}(\text{E-}\pi_2)\hspace*{1cm}\frac{}{\pi_2(<\lambdaValue{V_1}, \lambdaValue{V_2}>)\to\lambdaValue{V_2}}(\text{E-}\pi'_2) 250 | \end{equation*} 251 | 252 | \subsection{Listas} 253 | 254 | \paragraph{Tipos} 255 | \[\sigma::= \dots~|~[\sigma]\] 256 | 257 | \paragraph{Términos} 258 | \[M,~N~,O~::=~\dots~|~[]_{\sigma}~|~M::N~|~\texttt{case } M \texttt{ of } {[] \leadsto N | h::t \leadsto O}~|~\text{foldr } M \text{ base} \leadsto N; \text{rec}(h,r)\leadsto O\] 259 | 260 | Los términos son: 261 | \begin{itemize} 262 | \item \([]_{\sigma}\) es la lista vacía de tipo \(\sigma\) 263 | \end{itemize} 264 | \paragraph{Axiomas y reglas de tipado} 265 | \begin{multicols}{2} 266 | \[\frac{}{\judgeType{\Gamma}{\List{\sigma}}{[\sigma]}}(\text{T-Vacio})\] 267 | 268 | \vspace*{5mm} 269 | \[\frac{\judgeType{\Gamma}{M}{\sigma}\hspace*{5mm}\judgeType{\Gamma}{N}{[\sigma]}}{\judgeType{\Gamma}{M::N}{[\sigma]}}(\text{T-}::)\] 270 | 271 | \vspace*{5mm} 272 | \[\frac{\judgeType{\Gamma}{M}{[\sigma]}\hspace*{5mm}\judgeType{\Gamma}{N}{\tau}~\hspace*{5mm}\judgeType{\Gamma,h:\sigma,t:[\sigma]}{O}{\tau}}{\judgeType{\Gamma}{\lambdaListCase{M}{N}{O}}{\tau}}(T-Case)\] 273 | 274 | \vspace*{5mm} 275 | \[\frac{\judgeType{\Gamma}{M}{[\sigma]}\hspace*{5mm}\judgeType{\Gamma}{N}{\tau}~\hspace*{5mm}\judgeType{\Gamma,h:\sigma,r:\tau}{O}{\tau}}{\judgeType{\Gamma}{\lambdaListFold{M}{N}{O}}{\tau}}(T-Fold)\] 276 | 277 | \end{multicols} 278 | 279 | \paragraph{Valores} 280 | \(V~::= ...~|~\List{\sigma}~|~V::V\) 281 | 282 | \paragraph{Axiomas y reglas de evaluación} 283 | \begin{multicols}{2} 284 | \[\frac{M_1\to M_1'}{M_1 :: M_2 \to M'_1::M_2}(\text{E-}::\text{1})\] 285 | 286 | \vspace*{5mm} 287 | \[\frac{M_2\to M_2'}{V :: M_2 \to V::M'_2}(\text{E-}::\text{2})\] 288 | 289 | \vspace*{5mm} 290 | \[\frac{}{\lambdaListCase{\List{\sigma}}{N}{O}\to N}(\text{E-Case}[~])\] 291 | 292 | \end{multicols} 293 | \vspace*{5mm} 294 | \[\frac{}{\lambdaListCase{V_1::V_2}{N}{O}\to\multiReplaceBy{O}{h\leftarrow V_1,~t\leftarrow V_2}}(\text{E-Case}::)\] 295 | 296 | \vspace*{5mm} 297 | \[\frac{M\to M'}{\lambdaListCase{M}{N}{O}\to\lambdaListCase{M'}{N}{O}}(\text{E-Case}\text{1})\] 298 | 299 | \vspace*{5mm} 300 | \[\frac{}{\lambdaListFold{\List{\sigma}}{N}{O}\to N}(\text{E-Fold}[~])\] 301 | 302 | \vspace*{5mm} 303 | \[\frac{}{\lambdaListFold{V_1::V_2}{N}{O}\to \multiReplaceBy{O}{h\leftarrow V_1,~r\leftarrow(\lambdaListFold{V_2}{N}{O})}}(\text{E-Fold}::)\] 304 | 305 | \vspace*{5mm} 306 | \[\frac{M\to M'}{\lambdaListFold{M}{N}{O}\to\lambdaListFold{M'}{N}{O}}(\text{E-Fold}\text{1})\] 307 | 308 | 309 | \subsection{Árboles binarios} 310 | 311 | \paragraph{Tipos} 312 | \[\sigma,\tau~::= \dots~|~AB_\sigma\] 313 | 314 | \paragraph{Términos} 315 | \[M,~N~::=~\dots~|~\text{Nil}_\sigma~|~\text{Bin}(M, N, O)~|~\text{raiz}(M)~|~\text{der}(M)~|~\text{izq}(M)~|~\text{esNil}(M)\] 316 | \paragraph{Axiomas y reglas de tipado} 317 | \begin{equation*} 318 | \begin{gathered} 319 | \frac{}{\judgeType{\Gamma}{\text{Nil}_\sigma}{AB_\sigma}}(\text{T-Nil})\hspace*{1cm} 320 | \frac{\judgeType{\Gamma}{M}{AB_\sigma}\hspace*{5mm}\judgeType{\Gamma}{N}{\sigma}\hspace*{5mm}\judgeType{\Gamma}{O}{AB_\sigma}}{\judgeType{\Gamma}{\text{Bin}(M, N, O)}{AB_\sigma}}(\text{T-Bin}) \\ 321 | \vspace*{5mm}\\ 322 | \frac{\judgeType{\Gamma}{M}{AB_\sigma}}{\judgeType{\Gamma}{\text{raiz}(M)}{\sigma}}(\text{T-raiz})\hspace*{1cm} 323 | \frac{\judgeType{\Gamma}{M}{AB_\sigma}}{\judgeType{\Gamma}{\text{der}(M)}{AB_\sigma}}(\text{T-der}) 324 | \vspace*{5mm} \\ 325 | \frac{\judgeType{\Gamma}{M}{AB_\sigma}}{\judgeType{\Gamma}{\text{izq}(M)}{AB_\sigma}}(\text{T-izq}) 326 | \hspace*{1cm} 327 | \frac{\judgeType{\Gamma}{M}{AB_\sigma}}{\judgeType{\Gamma}{\text{isNil}(M)}{Bool}}(\text{T-isNil}) 328 | \end{gathered} 329 | \end{equation*} 330 | 331 | \paragraph{Valores} 332 | \[V~::=~\dots~|~\text{Nil}~|~\text{Bin}(V,V,V)\] 333 | 334 | \paragraph{Axiomas y reglas de evaluación} 335 | \begin{equation*} 336 | \frac{M\to M'}{\text{Bin}(M,N,O)\to \text{Bin}(M',N,O)}(\text{E-Bin1})\hspace*{1cm}\frac{N\to N'}{\text{Bin}(V,N,O)\to \text{Bin}(V,N',O)}(\text{E-Bin2}) 337 | \end{equation*} 338 | \vspace*{5mm} 339 | \begin{equation*} 340 | \frac{O\to O'}{\text{Bin}(V_1,V_2,O)\to \text{Bin}(V_1,V_2,O')}(\text{E-Bin3}) 341 | \end{equation*} 342 | \vspace*{5mm} 343 | \begin{equation*} 344 | \frac{M\to M'}{\text{raiz}(M)\to\text{raiz}(M')}(\text{E-Raiz1})\hspace*{1cm}\frac{}{\text{raiz}(\text{Bin}(V_1,V_2,V_3))\to V_2}(\text{E-Bin3}) 345 | \end{equation*} 346 | \vspace*{5mm} 347 | \begin{equation*} 348 | \frac{M\to M'}{\text{der}(M)\to\text{der}(M')}(\text{E-Der1})\hspace*{1cm}\frac{}{\text{der}(\text{Bin}(V_1,V_2,V_3))\to V_3}(\text{E-Der2}) 349 | \end{equation*} 350 | \vspace*{5mm} 351 | \begin{equation*} 352 | \frac{M\to M'}{\text{izq}(M)\to\text{izq}(M')}(\text{E-Izq1})\hspace*{1cm}\frac{}{\text{izq}(\text{Bin}(V_1,V_2,V_3))\to V_1}(\text{E-Izq2}) 353 | \end{equation*} 354 | \hspace*{5mm} 355 | \begin{equation*} 356 | \frac{}{\text{isNil}(M)\to\text{izq}(M')}(\text{E-isNil1})\hspace*{1cm}\frac{}{\text{isNil}(\text{Bin}(V_1,V_2,V_3))\to false}(\text{E-isNilBin}) 357 | \end{equation*} 358 | \hspace*{5mm} 359 | \begin{equation*} 360 | \frac{}{\text{isNil}(\text{Bin}(V_1,V_2,V_3))\to true}(\text{E-isNilNil}) 361 | \end{equation*} 362 | 363 | \newpage 364 | \section{Javascript} 365 | \paragraph{Declaración de variables} 366 | \begin{centrado} 367 | \begin{minted}{javascript} 368 | // Declaración de variables 369 | let miVar = 1; 370 | var suVar = 2; 371 | 372 | // Declaración de constante, no pueden ser modificadas. 373 | const miConstante = 3; 374 | \end{minted} 375 | \end{centrado} 376 | 377 | Y es \textbf{case-sensitive}, es decir \javascript{unavariable} y \javascript{unaVariable} no son las mismas variables. 378 | 379 | \paragraph{Tipos} 380 | 381 | \begin{itemize} 382 | \item \javascript{number}: Los números, no hay distinción entre enteros y punto flotantes. Contiene a las constantes \javascript{-Infinity},\javascript{+Infinity}, \javascript{NaN}. 383 | \item \javascript{boolean}: Los literales \javascript{true} y \javascript{false} con las operaciones \javascript{\&\&}, \javascript{!} y \javascript{||}. 384 | \item \javascript{string}: Secuencias de cero o más carácteres entre comillas simples o dobles. 385 | \item \javascript{null}: Un único valor \javascript{null} (nada, valor desconocido). 386 | \item \javascript{undefined}: Un único valor \javascript{undefined} (el valor no está definido). 387 | \end{itemize} 388 | 389 | Podemos usar \javascript{typeof} para saber el nombre del tipo de la expresión. 390 | 391 | \begin{itemize} 392 | \item \javascript{Arrays:} \javascript{[], [1,2,true], new Array()} 393 | 394 | \javascript{-[-] , push(-) , pop() , shift() , unshift(_)} 395 | \end{itemize} 396 | 397 | \paragraph{Tipado} 398 | El tipado se hace de manera \textbf{dinámica} (en tiempo de ejecución) y \textbf{débil} (se pueden comparar cosas que no son del mismo tipo porque hay conversión automática). 399 | 400 | Por ejemplo: 401 | \begin{centrado} 402 | \begin{minted}[breaklines]{javascript} 403 | let a = 1 // a = 1 404 | a += '1' 405 | // a = '11' (El entero, se convierte automaticamente en un string) 406 | \end{minted} 407 | 408 | \end{centrado} 409 | 410 | \begin{multicols}{2} 411 | \begin{minted}{javascript} 412 | 1 == '1' // true 413 | 1 === '1' // false 414 | 0 == false // true 415 | 0 === false // false 416 | 1 == true // true 417 | \end{minted} 418 | \vfill\null 419 | \columnbreak 420 | \begin{minted}{javascript} 421 | false == '' // true 422 | false === 'false' // false 423 | null == undefined // true 424 | null === undefined // false 425 | \end{minted} 426 | \end{multicols} 427 | 428 | \newpage 429 | \paragraph{Flujos de control} 430 | \begin{centrado} 431 | \begin{minted}{javascript} 432 | if (cond) { ... } else { ... } 433 | 434 | while (cond) { 435 | //cuerpo 436 | } 437 | 438 | do { 439 | //cuerpo 440 | } while (cond); 441 | \end{minted} 442 | 443 | \end{centrado} 444 | 445 | \paragraph{Definición de funciones} 446 | \begin{centrado} 447 | \begin{minted}{javascript} 448 | function nombre(arg1, ..., argn){ 449 | //cuerpo 450 | } 451 | 452 | let nombre = function(arg1, ..., argn){ 453 | //cuerpo 454 | } 455 | 456 | let nombre = (arg1, ..., argn) => { 457 | //cuerpo 458 | } 459 | \end{minted} 460 | 461 | \end{centrado} 462 | 463 | \paragraph{Objetos} 464 | \begin{centrado} 465 | \begin{minted}[breaklines]{javascript} 466 | let o = { 467 | a : 1, 468 | b : function(n) { 469 | return this.a + n // this hace referencia a o 470 | } 471 | } 472 | 473 | o.a // 1 Proyeccion del atributo a 474 | 475 | o['a'] // 1 (Proyeccion del atributo a) 476 | 477 | o.b(1) // 2 (Proyeccion y ejecucion del metodo b) 478 | 479 | 480 | o.b = function() { return this.a } // Redefinimos o.b 481 | 482 | o.c = true // Agrega el atributo c a o. 483 | o['c'] = false // Redefinimos el atributo c de o. 484 | delete o.a // Elimina el atributo a de o. 485 | 486 | 487 | \end{minted} 488 | \end{centrado} 489 | 490 | \begin{centrado} 491 | \begin{minted}[breaklines]{javascript} 492 | 'c' in o // true (Checkea si c es una propiedad de o) 493 | 'd' in o // false 494 | 495 | // Iteracion sobre todas las propiedades de o. 496 | for(let p in o){ 497 | ... 498 | } 499 | \end{minted} 500 | \end{centrado} 501 | \begin{centrado} 502 | \begin{minted}[breaklines]{javascript} 503 | 504 | let p = o // Creamos una referencia a o. 505 | 506 | let f = o.b 507 | // Extraemos el metodo b de f. Dejamos las variable this desligada. 508 | 509 | let o2 = { i: f, a: true} 510 | // Crea el objeto o2, con la función f en su atributo i. 511 | 512 | o2.f() // true 513 | 514 | let o3 = Object.assign({}, o, o2) 515 | // Copia las propiedade de o y o2 en o3. Hace un shallow copy, es decir si una atributo de o2 u o3 es una referencia, entonces en o, ese atributo va a ser una referencia al mismo objeto que en o2 516 | \end{minted} 517 | \end{centrado} 518 | 519 | \paragraph{Herencia} 520 | Todos los objetos tiene una propiedad privada llamada \javascript{[[Prototype]]} cuyo valor es \javascript{null} u otro objeto que es su \textbf{prototipo}. Esta propiedad induce una cadena de prototipado sin ciclos que finaliza con \javascript{null}. 521 | 522 | Cuando intentamos acceder a un método inexistente de un objeto, el mismo se busca en la cadena de prototipado del mismo hasta encontrar el primer objeto de la cadena que lo define. Si llegamos a \javascript{null} y el método no fue encontrado, entonces hay un error. 523 | 524 | \begin{centrado} 525 | \begin{minted}[breaklines]{javascript} 526 | Object.setPrototypeOf(o, prot) // Hace que el prototipo de o sea prot. 527 | Object.getPrototypeOf(o) // Devuelve el objeto que es protipo de o. 528 | 529 | o.__proto__ // Otra forma de conseguir el prototipo de o. 530 | o.__proto__ = o1 // Otra forma de setear el prototipo de o 531 | \end{minted} 532 | \end{centrado} 533 | 534 | Cuando ejecutamos un método de la cadena de prototipado, el método evaluado liga \javascript{this} al objeto llamó al método, es decir, si tenemos: 535 | 536 | \begin{centrado} 537 | \begin{minted}[breaklines]{javascript} 538 | let o1 = { a: 1} 539 | let o2 = { b: function(){ 540 | return this.a 541 | } 542 | } 543 | \end{minted} 544 | \end{centrado} 545 | \begin{centrado} 546 | \begin{minted}[breaklines]{javascript} 547 | o1.__proto__= o2 548 | 549 | o1.b(); 550 | // Busca b en o1 y no lo encuentra, el proximo objeto en la cadena es o2, encuentra b y liga this = o1, luego ejecuta el método. 551 | \end{minted} 552 | \end{centrado} 553 | 554 | Para crear una copia de un objeto y asignarle a esa copia el objeto original como prototipo usamos \javascript{Object.create}. 555 | 556 | Además javascript provee el prototipo \javascript{Object.prototype} que es prototipo de todos los objetos y provee metodos básicos como \javascript{hasOwnProperty()} que indica si el objeto contiene una propiedad no heredada y \javascript{toString()} que devuelve un string que representa al receptor. 557 | 558 | \paragraph{Cadenas de prototipado} 559 | 560 | \begin{centrado} 561 | \begin{minted}[breaklines]{javascript} 562 | let o1 = { ... } 563 | // o1 ---> Object.prototype ---> null 564 | 565 | let o2 = Object.create(o1) 566 | // o2 ---> o1 ---> Object.prototype ---> null 567 | 568 | let o = Object.create(null) 569 | // o ---> null 570 | \end{minted} 571 | \end{centrado} 572 | 573 | \paragraph{Constructores} Son funciones que generan objetos. Cuando declaramos un constructor \javascript{C}, javascript crea un objeto llamado \javascript{C.prototype} que se asigna como prototipo de todos los objetos creados con dicha función. Por ejemplo: 574 | 575 | \begin{centrado} 576 | \begin{minted}[breaklines]{javascript} 577 | // Constructor Punto, tiene la siguiente cadena de prototipado: 578 | // Punto --> Function.prototype --> Object.prototype --> null 579 | function Punto(x,y){ 580 | this.x = x; 581 | this.y = y; 582 | this.mvx = function(d){ 583 | this.x += d; 584 | } 585 | } 586 | 587 | // Objeto creado con el constructo punto 588 | o = new Punto(1,2) 589 | // o = Object{ x: 1, x:2, mvx: mvx()} y su cadena de prototipado es: 590 | // o --> Punto.prototype --> Object.prototype --> null 591 | \end{minted} 592 | \end{centrado} 593 | --------------------------------------------------------------------------------