Hoy me voy a atrever con un tema del que sólo he rascado la superficie, y que me está resultando complicado aunque no por eso deja de gustarme.

¿Podrías multiplicar números de 3 cifras sin equivocarte? ¿Y de 5? ¿Y de 10 cifras? Este es el tipo de tareas de muy bajo nivel que pueden resolver fácilmente los ordenadores, pero que a las personas se nos dan fatal porque cometemos errores y además somos insufriblemente lentas resolviendo estas tareas. Aún así, los ordenadores necesitan personas que los programen. ¿Qué hacer entonces para reducir la brecha entre la persona y la máquina? Hay dos opciones: o somos las personas las que aprendemos a trabajar a bajo nivel para acercarnos a la lógica de los ordenadores, o son los ordenadores (y especialmente los lenguajes de programación) los que cambian para usar abstracciones de más alto nivel que se parezcan más a la forma en que pensamos las personas. Para Bartosz Milewski la respuesta es simple: es más fácil cambiar a los ordenadores que a las personas.

En programación imperativa se utilizan comandos para modificar el estado de un programa: guarda esta valor en memoria, luego realiza esta operación, y cuando termines actualiza el valor que tenías almacenado en memoria con el resultado de la operación anterior. Parecen tareas de bastante bajo nivel, que le están diciendo al ordenador no sólo lo que tiene que hacer, sino que también le dicen cómo hacerlo. ¿Existe alguna alternativa que nos permita expresar solamente lo que queremos, y dejar que el ordenador decida cuál es la mejor forma de hacerlo?

Creo recordar que la primera vez que me di cuenta de que existía esa posibilidad fue durante una charla de Mario Fusco donde explicaba porqué habían introducido las lambdas en Java 8. Mario Fusco decía en su charla que a una niña pequeña le tienes que pedir: recoje tu libro de colorear, recoje los lápices, recoje la pelota… En cambio, si a esa misma niña ya un poco más crecida le pedimos: recoje tu habitación, ella misma decidirá que el libro de colorear y los lápices es mejor recogerlos juntos porque ambos se guardan en la misma estantería. De manera similar, los lenguages de programación deberían evolucionar para entender peticiones más complejas.

Category Theory Viaja en Metro

Category Theory es una rama de las matemáticas que permite describir las relaciones entre conjuntos de datos. Justamente éste es el tipo de problemas que solemos resolver mediante software. Por esa razón, cada vez más desarrolladores creen que Category Theory va a jugar un papel muy importante en el diseño de los lenguajes de programación modernos. Prueba de ello es que los lenguajes de programación más populares están incorporando elementos de Category Theory para adecuarse a los retos actuales de la industria del software.

Incluso, hay quien piensa que esta tendencia va a producir un cambio fundamental en nuestra forma de programar. Como Category Theory no hace ninguna suposición acerca de la forma de implementar las relaciones entre objetos (sólamente las describe mediante reglas matemáticas), cada lenguaje puede aprovechar sus ventajas para proporcionar sus propias formas idiomáticas de componer programas. Si más lenguajes de programación siguen tomando ideas de Category Theory, eso podría permitirnos a más desarrolladores aprovechar las características nativas del lenguaje desde la comodidad y la seguridad de Category Theory.

¿Y porqué esto es importante? No se me ocurre una mejor explicación que la charla de Eugenia Cheng en la Lambda World de 2017.

Mapa del metro de Los Angeles

(Foto de José Martín Ramírez Carrasco en Unsplash)

Me voy a permitir adaptar uno de los ejemplos que da Eugenia Cheng en su charla sobre el uso de Category Theory para solucionar un problema cotidiano: la necesidad que tenemos de desplazarnos. Imagina que estás en una ciudad y quieres viajar entre el punto A y el punto B. Digamos que decides ir en metro, y lo que haces es buscar en el plano del metro una ruta entre A y B. Puede que primero tengas que coger la línea azul en A, luego bajarte en C y, por último, cambiar a la línea verde que te lleva hasta B. Sin saberlo estás componiendo A → C → B.

¿Qué pasará luego cuando quieras regresar? Seguramente encontrarás una relación equivalente que anule la anterior: B → C → A.

El plano del metro funciona con unas reglas bastante simples que permiten encontrar, con relativa facilidad, rutas para viajar entre dos puntos. Además, las rutas tienen ciertas propiedades como la simetría que nos dan gratis otras operaciones como la posibilidad de regresar haciendo la misma ruta, pero en sentido contrario.

Eugenia Cheng también decía en su charla que a pesar de no ser exacto y de representar las distancias de manera aproximada, comparado con un mapa cartográfico, el plano del metro tiene ciertas ventajas que lo hacen más apropiado para los viajeros. Esta usabilidad es justamente lo que hace que Category Theory sea interesante para los programadores.

Por ejemplo, aunque viajar en avión sea muy diferente de viajar en metro, planificar un viaje en avión desde Barcelona a La Habana es fundamentalmente lo mismo que planificar un trayecto en metro dentro de Barcelona: en ambos casos se trata de encontrar rutas (arrows) y conexiones (objects). La diferencia más notable es que al planificar un viaje en avión eliges aeropuertos que pueden estar en diferentes países con sus fronteras y distintas zonas horarias, mientras que al planificar un viaje en metro elijes estaciones dentro de la misma ciudad. Lo que vengo a decir es que, aunque sabemos que un viaje en avión es muy diferente a un viaje en metro, la misma abstracción nos podría llegar a servir para representar cualquiera de los dos. Para mí eso es lo que hace Category Theory: nos permite centrarnos en solucionar el problema de viajar entre los puntos A y B, aunque en algunos casos vamos a necesitar un avión y en otros será suficiente con tomar el metro.

Finalmente

Bartosz Milewski empieza su charla de la ScalaIO de 2017 con una reflexión que me atrevo a transcribir muy libremente así:

Un ordenador no entiende de valor, sino que entiende de progreso, de realizar una tarea tras otra. A diferencia de los ordenadores, las personas tenemos una visión global, un propósito por el cual escribimos un programa: ya sea para ayudar a mantener un proyecto open-source o para que una empresa gane dinero.

Category Theory ofrece abstracciones que los programadores de Haskell y Scala están aprovechando para escribir programas de una forma menos imperativa, dando más peso al propósito que a los detalles de implementación. Aún así, Bartosz Milewski también alerta de que este estilo de programación introduce un nivel adicional de abstracción que los programadores tenemos que dominar.

Aunque Category Theory parece tener muchas aplicaciones dentro de la programación, no todos los programas se pueden escribir de esta manera. Hay algunos programadores que van a seguir necesitando trabajar a bajo nivel: por ejemplo, para hacer un servidor Web o un compilador. Sin embargo, para todos aquellos que nos dedicamos a otras cosas que no sea programar servidores Web, ni escribir compiladores, tengo la impresión de que aprender Category Theory nos vendrá muy bien.

El libro Category Theory for Programmers de Bartosz Milewski parece dar las claves para entender este cambio de paradigma (y digo parece porque aún no he terminado de leerlo, y mucho menos de comprenderlo en su toda su profundidad). Es más, una de las razones para escribir este post es para convencerme a mí mismo de retomar la lectura, que a veces se me hace difícil por la poca costumbre que tengo de pensar de la manera tan abstracta que me plantea este libro. Los libros que leo normalmente están relacionados con la tecnología o con la forma de hacer software, y son muy directos, casi prescriptivos en algunos casos. Comparativamente, encuentro que es más fácil razonar con Category Theory que con otros conceptos que se enseñan como dogma.

También estoy alternando la lectura con algo de prácticas con Scala y cats-effect. Esto parece ayudarme a mantener la motivación cuando las cosas se ponen demasiado “profundas”.

Pigs and fireworks