This commit is contained in:
Vladimir Lemus 2023-02-23 18:20:45 -06:00
parent 43f69d742e
commit 283a5234c6
4 changed files with 155 additions and 1 deletions

Binary file not shown.

View File

@ -213,7 +213,7 @@ Ya en la introducción habíamos mencionado una forma de ver a las funciones mat
\label{fig:func}
\end{center}
Las características del cálculo lambda pueden listarse:
Las características del cálculo $\lambda$ pueden listarse:
\begin{itemize}
\item Solo depende de funciones. Si no se puede escribir como función, no se puede incluir.
@ -222,6 +222,130 @@ Las características del cálculo lambda pueden listarse:
\item Todas las funciones son unitarias, sólo toman un argumento
\end{itemize}
El cálculo $\lambda$ fue iniciado en la década de los 30s del siglo $XX$ por Alonso Church. No fue la única persona trabajando en el área, Haskell Curry trabajo en la lógica combinatoria, Gödel en las funciones recursivas $\mu$ en las que podemos encontrar algunas similitudes, Emil Post en el sistema canónico de Post, o sistema de reescritura y Alan Turing con las máquinas de Turing. Todos ellos de alguna manera trataron de definir qué era un algoritmo y darle una estructura formal\footnote{Como vimos en la sección pasada los algoritmos existen incluso desde hace 2000 años, pero no había una teoría formal de ellos.}. Las funciones recursivas $\mu$ y las máquinas de Turing ya las vimos de rápido, en lo que sigue nos centraremos en la parte del trabajo de Church y Curry. Pero para ser justos hay que mencionar como funciona el sistema canónco de Post.
Se parte de una cantidad finitamente grande de cadenas de caracteres que serán manipuladas, de manera repetida son transformadas al aplicar un conjunto finito de reglas, formando un lenguaje regular. Al ser Turing completo, es equivalente a trabajar con máquinas de Turing. Ya sólo se estudia con interés histórico pues hay formalismos que incluyen las ideas de Post más usados hoy en día.
La idea de Post al crear el cálculo $\lambda$ era demostrar que el problema de la decisión de Hilbert no era resolvible por la aritmética de Peano. Lo que obtuvo fue un sistema para estudiar las matemáticas de una forma más general.
Con las reglas antes mencionadas sólo resta decir que para construir todas las funciones matemáticas en el cálculo $\lambda$ basta usar tres operaciones:
\begin{itemize}
\item Crear funciones que recibirán variables
\item Asociar una variable a la expresión
\item Aplicar una función a un argumento
\end{itemize}
¿Porque la diferencia entre asociar una variable y aplicar a un argumento? Tal como cuando definimos una función matemática del estilo $f(x)=x^2-3x$ las variable $x$ es más un marco donde eventualmente puede entrar un valor, alevaluar la ecuación en un número es que estamos aplicando la función a un argumento. Las variables son términos $\lambda$ y son la base de las definiciones deductivas del cálculo $\lambda$.
En el trato normal de las variables en el cálculo $\lambda$ los tipos no entran en juego, está des-tipado (no sé si así se dice, pero suena cagado).
Imaginemos que se tienen dos términos $\lambda$ $M$ y $N$, $MN$ también es un término $\lambda$, podría ser por ejemplo que $M$ es una función y $N$ una entrada (podría ser también una función). La forma más formal de escribirlo es $(M)N$ donde se dice que $N$ es una entrada aplicada a la función $M$. El paréntesis es operador \emph{aplicación} y se asocia a la izquierda (MN)P.
Pero realmente el orden de la aplicación es de izquierda a derecha, por ejemplo, si tenemos $\lambda x.E(x)$ lo que quiere decir es que con la entrada $x$ la función calcula $E(x).$
Veamos un ejemplo concreto. Se tiene:
\begin{lstlisting}{language=Haskell}
inc(x) = x+1
\end{lstlisting}
Lo que quiere decir que para incrementar $x$ se le suma $1$
\begin{lstlisting}{language=Haskell}
(x) -> x+1
\end{lstlisting}
Pero usando ya directamente la abstracción
\begin{equation*}
\lambda x.(x+1)
\end{equation*}
Si ahora tenemos la función
\begin{lstlisting}{language=Haskell}
sumcuad(x,y) = x^2+y^2
\end{lstlisting}
Que se traduce a
\begin{lstlisting}{language=Haskell}
(x,y)-> x^2+y^2
\end{lstlisting}
¿Cómo se pondría en la abastracción?
\begin{equation*}
\lambda x.(\lambda y.(x^2+y^2))
\end{equation*}
¡Muy bien! ¿Y ahora como se evalúa (aplicar a un argumento)? Para el caso del incremento al número $8$:
\begin{equation*}
\lambda x.(x+1)8
\end{equation*}
Vamos a un caso más abstracto, sea la composición de las funciones $f$ y $g$
\begin{equation*}
\lambda x.f(gx)
\end{equation*}
Pero en ese caso solo estamos dando como entrada a $x$ ¿y si quiero dejarlo como el esqueleto de una composición done también puedo darle como entrada las funciones $f$ y $g$?
\begin{equation*}
\lambda f.\lambda g. \lambda x. f(gx)
\end{equation*}
Con ese esqueleto ahora hagamos la composición de la función sucesor:
\begin{align*}
&(\lambda f.\lambda g. \lambda x. f(gx))(\lambda y.(y+1))(\lambda z.(z+1)) \\
&\rightarrow (\lambda g. \lambda x. ((\lambda y.(y+1))(gx)))(\lambda z.(z+1)) \\
&\rightarrow \lambda x.((\lambda y.(y+1))((\lambda z.(z+1))x))) \\
&\rightarrow \lambda x.((\lambda y.(y+1))(x+1)) \\
&\rightarrow \lambda x.((x+1)+1)
\end{align*}
\subsection*{Calculo $\lambda$ \emph{tipado}}
Una variante del cálculo $\lambda$ admite que se especifique el tipo de las variables a dar como argumento, así las funciones definidas se restringen al dominio dado.
Si en la función incremento sólo queremos operar sobre naturales
\begin{equation*}
\lambda x:\nu.(x+1)
\end{equation*}
Eso es el estilo Church, se infiere que al ser la entrada naturales la salida son naturales, pero el estilo Curry hace que toda la función sea definida dentro de los naturales
\begin{equation*}
(\lambda x.(x+1))\nu \rightarrow \nu
\end{equation*}
Si hay más de una variable la versión Post sería
\begin{equation*}
\lambda x:\nu.(\lambda y:\nu.(x^2+y^2))
\end{equation*}
Y la versión Curry
\begin{equation*}
\lambda x.(\lambda y.(x^2+y^2)):\nu \rightarrow \nu \rightarrow \nu
\end{equation*}
\subsection*{Operaciones de reducción}
Vamos ahora a expresar una función $\lambda$ en su forma más simple y pura
\begin{itemize}
\item \textbf{Reducción $\alpha$}: Renombrar variables. Se dice que dos funciones son $\alpha equivalentes$ cuando lo único que cambia es el nombre d ela variable ($\lambda x.(x+1)$ y $\lambda a.(a+1)$).
\item \textbf{Reducción $\beta$}: Remplaza variables por argumentos. Como ya hicimos líneas arriba.
\item \textbf{Reducción $\eta$}:
\end{itemize}
\section*{Programación funcional en \emph{Python}}
Declaraciones en lugar de procedimientos paso a paso.

BIN
tarea1.pdf Normal file

Binary file not shown.

30
tarea1.tex Normal file
View File

@ -0,0 +1,30 @@
\documentclass[10pt,a4paper]{article}
\usepackage[spanish]{babel}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{amsfonts}
\usepackage{amssymb}
%\usepackage{braket}
\author{Programación funcional para la física computacional}
\title{Tarea 1}
\begin{document}
\maketitle
\begin{enumerate}
\item Define la función factorial de forma recursiva, como lo vimos en clase, pero ahora en \emph{Haskell} (consejo: puedes librarte de el $if$ y $else$, $Haskell$ puede interpretar definiciones de funciones por casos).
\item A partir de la función factorial definida (sea la de $python$ o esta que hiciste en $Haskell$) construye la función combinatoria
\begin{equation*}
{n \choose r} = \frac{n!}{(n-r)!r!}
\end{equation*}
\item Construye en python un programa que genere la serie de Fibonacci de manera similar a nuestro ejemplo para el triángulo de Pascal (recuerda que la serie de Fibonacci esta dada como $F_0=0$, $F_1=1$ y $F_n=F_{n-1}+F_{n-2}$).
\item Usando el programa para obtener las filas del triágulo de Pascal realiza la expansiópn del término:
\begin{equation*}
(2x+1)^6
\end{equation*}
\item Genera los números primos de manera perezosa, usando el colador (la criba) de Eratostenes, pero ahora en Haskell (Graham Hutton te puede ayudar, pero intentalo primero y ya luego puedes revisar qué hace él: \url{https://www.youtube.com/watch?v=bnRNiE_OVWA}).
\end{enumerate}
\end{document}