Entradas

Mostrando entradas de octubre, 2023

OpenGL en Haskell (material opcional)

Imagen
 Es posible utilizar OpenGL en Haskell, pero les mentiría si les digo que es  un resultado garantizado... Depende de varias cosas. Y solo puedo dar notas para Ubuntu 18 al respecto.  Primero, hacer esto: sudo apt install freeglut3-dev Luego, hacer esto: cabal update  (cabal es un instalador de paquetes para ghc) Luego, hacer lo siguiente: cabal install GLUT (Se consume algo de espacio, para ser al menos medio giga... :( ) De salir todo bien, ahora inspeccionar el siguiente sitio:   https://archives.haskell.org/code.haskell.org/GLUT/examples/RedBook/   ...... Wuiiiii Tomar de aquí algún archivo y compilarlo. Por ejemplo, Robot.hs ghc -o robot Robot.hs (imagen de una versión mía modificada de Robot.hs) El código de Robot.hs lo coloco aquí, redundantemente. {-    Robot.hs (adapted from robot.c which is (c) Silicon Graphics, Inc.)    Copyright (c) Sven Panne 2002-2005 <sven.panne@aedion.de>    This file is part of HOpenGL ...

De un video de motos (solo a quien le interese, sin relación con el curso)

De tipos de motores de moto: https://youtu.be/EfZvGxijwRI?si=B-jeoeClGM1V7OSN (Para quienes gustan de este medio de transporte. Saludos.)

El problema de la edición de una cadena

Imagen
 En el problema de la edición de una cadena se tienen dos cadenas y se quiere conocer que tan disímiles o tan parecidas son de acuerdo con alguna medida. En esta implementación tenemos una respuesta...   d ms "" = length ms d "" ms = length ms d (a:ms) (b:ns) | a==b = d ms ns d (a:ms) (b:ns) | a/=b = 1+minimum [d ms (b:ns), d (a:ms) ns, d ms ns] y éste algoritmo es ¡triplemente recursivo! Para intentar ver sus llamadas, creamos un tipo de dato: data T = H String | Tri T T T deriving Show y aquí conformamos una construcción de las llamadas: si [] ms = H ms si ms [] = H ms si (a:bs) (c:cs) = Tri (si bs (c:cs)) (si bs cs) (si (a:bs) cs) En general, no es fácil ver árboles, pero lo siguiente puede ser pasado a LaTeX para visualizar algunos resultados (primero se genera la cadena, y se hace copy/paste a un archivo LaTeX; sería posible escribir el resultado directamente a un archivo, pero queda como opcional, pues aún no hemos visto cómo hacerlo). showTC (H i) = "\\T...

¡Pi en Haskell!

El número pi siempre está presente en Matemáticas y Computación.  Aquí está el cálculo de algunos de sus dígitos utilizando la fórmula de Leibniz pi/4=1-1/3+1/5-1/7+1/9.... Ver https://en.wikibooks.org/wiki/Calculus/Leibniz%27_formula_for_pi  pii n =   let     ls=1:(map (+2) ls)     inter = 1:(-1):inter   in     4*(sum (zipWith (*) (take n inter) (map (\x -> 1/x) (take n ls)))) La fórmula de Leibniz es mona, pero por aquí encontré que con éste algoritmo  https://en.wikipedia.org/wiki/Chudnovsky_algorithm se pueden hallar trillones de dígitos de pi. Ésta es la versión de este algoritmo en Python....   import decimal def binary_split ( a , b ): if b == a + 1 : Pab = - ( 6 * a - 5 ) * ( 2 * a - 1 ) * ( 6 * a - 1 ) Qab = 10939058860032000 * a ** 3 Rab = Pab * ( 545140134 * a + 13591409 ) else : m = ( a + b ) // 2 Pam , Qam ,...

El fascinante triángulo de Pascal.

El triángulo de Pascal aparece en diversos contextos, ver:  https://en.wikipedia.org/wiki/Pascal%27s_triangle Para ver que la construcción where no sólo es estética, calcular take 25 (map pasTri [1..]) take 25 (map pasTri2 [1..]) de los programas de abajo y comparar la eficiencia de las versiones... pasTri es en efecto exponencial, y pasTri2 es lineal. pasTri 1 = [1] pasTri 2 = [1,1] pasTri n | n>2 = zipWith (+) (pasTri (n-1)++[0]) ([0]++pasTri(n-1)) pasTri2 1 = [1] pasTri2 2 = [1,1] pasTri2 n | n>2 = zipWith (+) (ls++[0]) ([0]++ls)           where             ls = pasTri2 (n-1) -- Observar que... -- [1,1] --   [1,1] -- ------- -- [1,2,1] --   [1,2,1] -- --------- -- [1,3,3,1] --   [1,3,3,1] -- ------------   -- [1,4,6,4,1]    

Impresión, inserción y creación aleatoria de árboles binarios

Para tener algunas funciones extras en árboles binarios (con una  representación ligeramente alternativa a la nuestra) sería bueno visitar el siguiente sitio: https://www.anardil.net/2018/binary-tree-in-haskell.html

Datos inductivos (recursivos)

 En Haskell algunos árboles binarios con nodos interiores decorados se  representan así data Bin = Hoja Int | B Int Bin Bin deriving Show La parte "Hoja Int" la podemos interpretar como las hojas del árbol, ya sin descendientes. La parte "B Int Bin Bin" hace referencia a la parte de nodos internos (raíz y no hojas) que lleva la información en la parte superior de un triángulo en "Int" y en la rama izquierda tiene un árbol de tipo Bin, así como en la parte derecha. Teniendo presente ésto, una función típica (endomorfismo) sería:   arbolConstante (Hoja n) = Hoja 2 arbolConstante (B n izq der) = B 2 (arbolConstante izq) (arbolConstante der)   Esta función toma un árbol binario y lo transforma en otro árbol binario con todo nodo valiendo 2. Otro ejemplo sería el de sumar todos los elementos de un árbol de este tipo: sumaArbol (Hoja n) = n sumaArbol (B n izq der) = n+sizq+sder               where  ...

Scheme y Haskell, ligera comparativa

 Scheme es un lenguaje de programación interesante, pero hay que reconocer que su sintaxis, llena de paréntesis, no parece actualizada. De todas formas, un rápido vistazo a un par de programas clásicos en este programa dará  idea de cómo programar aquí, en Scheme. (define (fact n)     (if (eq? n 0) 1         (* n (fact (- n 1))))) (define (fib n)    (if (or (eq? n 0) (eq? n 1)) 1        (+ (fib (- n 1)) (fib (- n 2))))) Como vemos, los paréntesis abundan. Podemos cargar este programa  en chez scheme, por ejemplo, y obtener: Chez Scheme Version 9.5 Copyright 1984-2017 Cisco Systems, Inc. > (load 'ejemplo.scm)   Exception in load: ejemplo.scm is not a string   Type (debug) to enter the debugger.   > (load "ejemplo.scm")   > (fact 10)   3628800   > (fib 10)   89   >  Así que los programas de fact y fib en Scheme tienen muchos p...

La entrada y salida en Haskell

Para cualquier lenguaje de programación existente, la tarea de entrada y salida es algo bastante común y convencional. No tanto así para Haskell. Aquí hay varios ejemplos para, elementalmente, tratar el tema de  entrada y salida desde el punto de vista haskeliano práctico. Dado que la teoría detrás, llamada teoría de mónadas, puede parecer particularmente intimidante, la dejamos para después. Mientras, vale trabajar directamente inspirándose en los ejemplos comentados en éste capítulo:   http://learnyouahaskell.com/input-and-output

Primeras nociones de funciones

 Hemos explicado en clase algunas nociones de funciones. Ésta es la versión ingenua de la función de Fibonacci, función típica en la enseñanza de la programación por su naturaleza doblemente  recursiva. En este caso, se le deja a Haskel la discriminación por casos, por un algoritmo interno llamado "pattern matching" o casamiento de patrones. Notemos cómo cada seudo-ecuación tiene un caso que excluye a los demás.  Además, es digno notar que la parte de la barrita vertical es para ampliar las posibilidades de discriminación, con un técnica de filtrado: fib 0 = 1 fib 1 = 1 fib n | n>0 = fib(n-1)+fib(n-2) En este caso, tenemos una definición más directa que la anterior, aceptada en otros lenguajes funcionales previos, tales como Scheme (ver los sitios www.scheme.org, www.scheme.com y https://racket-lang.org/, para quienes tengan curiosidad): nfib n = if n==0 || n==1 then 1 else nfib(n-1) + nfib(n-2) Otra versión, ésta vez eficiente, y apoyada en una noción de lista infinit...

Noción de flecha, diagramas

 Debido a que las funciones son componentes en la construcción de otras funciones, más complicadas, y haciendo eco de la llamada de procedimientos en lenguajes tales como C y Python, aprendemos aquí la técnica de composición de funciones.

Conjuntos

 Repasamos aquí la teoría de conjuntos con dos propósitos: Utilizarlos como una orientación teórica en la construcción de dominios en las funciones de Haskell, y, también, utilizarlos como una estructura de datos ya provista directamente dentro de un paquete en Haskell.  Repasamos la noción de conjunto vacío, subconjunto, pertenencia, union, intersección y diferencia (complemento) de conjuntos, así como la noción de cardinalidad y de conjunto potencia.

Visión por categorías

Pensamos primero en que existen algo conocidos como "flechas". Las flechas tienen tres componentes, dos objetos, uno llamado "fuente" y otro "blanco" y un "nombre" (realmente, un morfismo). Se pueden pensar como una tripleta: (A,B,f), en donde A es la fuente, B el blanco, y f siendo el nombre). Para un conjunto de flechas, es posible que haya composición de flechas: (A,B,f) y (B,C,g) crean una nueva flecha (A,C,g o f), en donde (g o f) (composición) es el nuevo nombre de la flecha (o nuevo morfismo). a) La composición es una operación no conmutativa. b) Tiene una identidad, tal que (A,A,f) y (A,A,IdA) nos permite tener (A,A,IdA o f) = (A,A,f), por ejemplo c) La composición es una operación asociativa. d) Para algunas flechas, es posible tener flechas inversas. f) Diagramas de persecución (chasing diagrams): Son diagramas que nos permiten razonar con flechas. f A ------> B \ | \ | g g o f | \/ v ...

Bienvenidos

Hola. Sería buena idea consultar por ahora los siguientes sitios: www.haskell.org www.erlang.org (lenguajes de programación) y https://edu.anarcho-copy.org/Programming%20Languages/Haskell/Learn%20You%20a%20Haskell%20for%20Great%20Good.pdf (para tener una copia en pdf de un excelente libro sobre el tema). Como complemento, de animarse algún día, pueden leer: https://book.realworldhaskell.org/read/