diff options
| author | Juan Marin Noguera <juan@mnpi.eu> | 2023-06-20 22:40:37 +0200 | 
|---|---|---|
| committer | Juan Marin Noguera <juan@mnpi.eu> | 2023-06-20 22:40:37 +0200 | 
| commit | 2f9eb7a94819a08937ba08320a142b7f0be407fd (patch) | |
| tree | 82f5829690485a5334899d3dceb2ab5db510adee /ch7_programming.tex | |
| parent | 69463a2c9f6b614ed98d6f9c09bb2d2666702e90 (diff) | |
(Pre)final
Diffstat (limited to 'ch7_programming.tex')
| -rw-r--r-- | ch7_programming.tex | 84 | 
1 files changed, 60 insertions, 24 deletions
| diff --git a/ch7_programming.tex b/ch7_programming.tex index 0756a3f..9bf856f 100644 --- a/ch7_programming.tex +++ b/ch7_programming.tex @@ -62,7 +62,7 @@ partes no funcionales se pueden formalizar de otra forma más tradicional o  mediante una construcción que involucra categorías de Kleisli, como veremos a  continuación. -\section{La categoría $\bType$} +\section{La categoría Type} % Text mode Type so that header is in uppercase  Por lo general, los tratamientos categóricos de la programación funcional se  basan en una categoría $\bType$ cuyos objetos son tipos de datos y cuyos @@ -235,6 +235,13 @@ $\bType$.    \mathtt{const\ }(\circ)_{a,b,c}:(b\to c)\to(a\to b)\to(a\to c) & = \lambda x.g(fx)\\    \mathtt{const\ }1_a:a\to a & = \lambda x.x\\  \end{align*} +La definición de $(\circ)$ muestra un patrón común en programación funcional, en +el que una función de varios parámetros no se define como de tipo $(a,b)\to c$ +sino de tipo $a\to b\to c$, notación que equivale a $a\to(b\to c)$. Esto tiene +la ventaja de ser más cómodo, pues si $f:a\to b\to c$, $x:a$ e $y:b$, podemos +escribir $fxy$ en vez de $f(x,y)$. Sin embargo, la mayor ventaja viene de +poder definir funciones parciales como $fx:b\to c$, que son útiles en algunos +casos.  \section{Funtores} @@ -339,7 +346,7 @@ El uso de endofuntores permite trasladar funciones para usarlas en subcategoría  que nos resulten más convenientes. Sin embargo, también puede ser deseable  trabajar en categorías que no sean subcategorías de $\bType$, y en ese aspecto  las categorías de Kleisli son muy útiles en la práctica, como se muestra en -\cite{monad}. Esto se debe a que el uso de estas categorías permite tratar +\cite{monads}. Esto se debe a que el uso de estas categorías permite tratar  funciones de tipo $a\to Tb$ <<como si fueran>> de tipo $a\to b$, lo que es útil  porque $Tb$ suele representar un resultado del tipo $b$ <<con alguna pega>>,  como que en vez de un valor de tipo $b$ puede haber un error, o una cantidad @@ -389,15 +396,16 @@ definen como un sinónimo de tipo con un parámetro junto con definiciones para  $\eta$ y $(\Rightarrow)$.\cite[p. 6]{haskmon}  \begin{example} -  Algunos de los ejemplos en (\ref{ex:monads}) son mónadas. +  Algunos de los ejemplos en (\ref{ex:monads}) son muy comunes en programación +  funcional.\cite[pp. 17--24]{haskmon}    \begin{enumerate}    \item En la mónada identidad, $x\Rightarrow f$ es la evaluación $f(x)$.    \item El funtor $\mathtt{result}_d$ admite la mónada dada por el ejemplo      \ref{enu:monad-result} en dicha lista. Sean $d$ es el tipo de los errores, -    $x:[\,b\,|\,d\,]$ y $f:b\to[\,c|\,d]$, si $x$ es un elemento de $b$, +    $x:[\,b\,|\,d\,]$ y $f:b\to[\,c|\,d\,]$, si $x$ es un elemento de $b$,      $x\Rightarrow b$ equivale a $fx$ viendo $x$ como elemento de $b$, y si $x$      está en $d$, $x\Rightarrow f$ devuelve $x$ visto como elemento de -    $[\,c|\,d\,]$. +    $[\,c\,|\,d\,]$.      \begin{align*}        \eta_a & = \lambda x.\langle x\rangle_1        & (\Rightarrow)_{a,b} & = \lambda x.\lambda f.\,\mathtt{match}\ x\ \{f;\ \lambda e.e\} @@ -451,20 +459,53 @@ respectivamente, aunque también se pueden definir operaciones básicas para otr  propósitos como dibujar en la pantalla para crear interfaces gráficas, recibir  movimientos del ratón, manipular ficheros y directorios, conectarse a Internet,  etc. - -Las operaciones en \texttt{IO} son las siguientes: -\begin{enumerate} -\item $\eta_a:a\to\mathtt{IO}\,a$ recibe un valor y devuelve la acción que, sin -  hacer nada, devuelve dicho valor. -\item Si $x:\mathtt{IO}\,a$ y $f:a\to\mathtt{IO}\,b$, $x\Rightarrow f$ devuelve -  la acción consistente en ejecutar la acción $x$, pasar el resultado devuelto a -  $f$ y ejecutar la acción devuelta por $f$, devolviendo su valor. -\item Si $x:\mathtt{IO}(\mathtt{IO}\,a)$, $\mu_ax$ es la acción que ejecuta $x$ -  y, a continuación, ejecuta la acción devuelta por $x$, devolviendo su valor. -\item Si $f:a\to b$, $\mathtt{IO}\,f:\mathtt{IO}\,a\to\mathtt{IO}\,b$ toma una -  acción $x$ y devuelve una acción que ejecuta $x$ y devuelve el resultado de -  aplicar $f$ al valor devuelto por la acción. -\end{enumerate} +\begin{samepage} +  Las operaciones de la mónada \texttt{IO} son las siguientes: +  \begin{enumerate} +  \item $\eta_a:a\to\mathtt{IO}\,a$ recibe un valor y devuelve la acción que, +    sin hacer nada, devuelve dicho valor. +  \item Si $x:\mathtt{IO}\,a$ y $f:a\to\mathtt{IO}\,b$, $x\Rightarrow f$ +    devuelve la acción consistente en ejecutar la acción $x$, pasar el resultado +    devuelto a $f$ y ejecutar la acción devuelta por $f$, devolviendo su valor. +  \item Si $x:\mathtt{IO}\,(\mathtt{IO}\,a)$, $\mu_ax$ es la acción que ejecuta $x$ +    y, a continuación, ejecuta la acción devuelta por $x$, devolviendo su valor. +  \item Si $f:a\to b$, $\mathtt{IO}\,f:\mathtt{IO}\,a\to\mathtt{IO}\,b$ toma una +    acción $x$ y devuelve una acción que ejecuta $x$ y devuelve el resultado de +    aplicar $f$ al valor devuelto por la acción. +  \end{enumerate} +\end{samepage} + +Estas operaciones permiten definir cualquier programa interactivo. Por ejemplo, +si $\mathtt{unit}_a:a\to\mathtt{IO}_a$ y +$\mathtt{bind}_{a,b}:\mathtt{IO}_a\to(a\to\mathtt{IO}_b)\to\mathtt{IO}_b$ son +las operaciones $\eta$ y $(\Rightarrow)$ de \texttt{IO}, y extendemos la +sintaxis para poder escribir $\mathtt{bind}_{a,b}\,x\,f$ como $x\Rightarrow f$, +con asociatividad por la izquierda, podemos escribir una cadena de caracteres, +representada como una lista de \texttt{Char}, con la siguiente función. +\begin{align*} +  & \mathtt{const\ forIO}_a:(a\to \mathtt{IO}_{()})\to\mathtt{list}_a\to\mathtt{IO}_{()} =\\ +  & \quad\quad \lambda l.\lambda f.\,\mathtt{match}\ l\ \{ +    \mathtt{unit};\ \lambda c.(\mathtt{putChar}\,c_1\Rightarrow\lambda x.\mathtt{forIO}_a\,f\,c_2)\}\\ +  & \mathtt{const\ putString} : \mathtt{list}_{\mathtt{Char}}\to\mathtt{IO}_{()} +    = \mathtt{forIO}\,\mathtt{putChar} +\end{align*} +Del mismo modo podemos querer leer líneas completas de la entrada: +\begin{align*} +  & \mathtt{const\ getLine}:\mathtt{IO}_{\mathtt{list}_{\mathtt{Char}}} = +    \mathtt{getChar}\Rightarrow\\ +  & \quad\quad (\lambda c.\, +    \mathtt{if}\ \{c\text{ es un salto de línea}\}\ \mathtt{then}\ \mathtt{unit}\,\langle()\rangle_1\, +  %\\& \quad\quad\phantom{(\lambda c.\,} +    \mathtt{else}\ \mathtt{getLine}\Rightarrow\lambda s.\langle(c,s)\rangle_2) +\end{align*} +El programa principal sería entonces un elemento de tipo $\mathtt{IO}_{()}$, +como el siguiente: +\begin{multline*} +  \mathtt{putString}\,\text{``¿Cómo te llamas? ''}\Rightarrow\lambda\_. +  (\mathtt{getLine}\Rightarrow\\ +  \lambda n.\mathtt{putString}\,\text{``¡Hola, ''}\Rightarrow +  (\lambda\_.\mathtt{putString}\ n)\Rightarrow(\lambda\_.\mathtt{putString}\,\text{``!''})) +\end{multline*}  En la práctica es común querer combinar la acción de varias mónadas. Para ello  se usan \conc{transformadores de mónadas}, que no son otra cosa que @@ -629,11 +670,6 @@ vez permite razonar sobre programas imperativos con un alto nivel de abstracció  %   \end{enumerate}  % \end{example} -% TODO Explicar vagamente la ausencia de coproductos -% TODO Funtores sobre listas -% TODO Transformaciones naturales -% TODO Las mónadas típicas -  %%% Local Variables:  %%% mode: latex  %%% TeX-master: "main" | 
