tag div body attribute javascript functional-programming

javascript - div - meta html



¿Qué significan los efectos algebraicos en la PF? (2)

Es difícil obtener una sólida comprensión teórica de los efectos algebraicos sin una base en la teoría de categorías, por lo que intentaré explicar su uso en términos sencillos, posiblemente sacrificando cierta precisión.

Un efecto computacional es cualquier cálculo que incluya una alteración de su entorno. Por ejemplo, cosas como la capacidad total del disco, la conectividad de la red son efectos externos, que desempeñan un papel en operaciones como leer / escribir archivos o acceder a una base de datos. Todo lo que una función produce, además del valor que calcula, es un efecto computacional. Desde la perspectiva de esa función, incluso otra función que accede a la misma memoria que esa función puede considerarse un efecto.

Esa es la definición teórica. En la práctica, es útil pensar en un efecto como cualquier interacción entre una subexpresión y un control central que maneja los recursos globales en un programa. Algunas veces, una expresión local puede necesitar enviar mensajes al control central durante la ejecución, junto con suficiente información para que una vez que se realice el control central, pueda reanudar la ejecución suspendida.

¿Por qué hacemos esto? Porque a veces las bibliotecas grandes tienen cadenas muy largas de abstracciones, que pueden ensuciarse. El uso de "efectos algebraicos" nos da una especie de atajo para pasar cosas entre abstracciones, sin pasar por toda la cadena.

Como ejemplo práctico de JavaScript, tomemos una biblioteca de IU como ReactJS. La idea es que la IU se pueda escribir como una simple proyección de datos.

Esto por ejemplo, sería la representación de un botón.

function Button(name) { return { buttonLabel: name, textColor: ''black'' }; } ''John Smith'' -> { buttonLabel: ''John Smith'', textColor: ''black'' }

Usando este formato, podemos crear una larga cadena de abstracciones compactables. Al igual que

function Button(name) { return { buttonLabel: name, textColor: ''black'' }; } function UsernameButton(user) { return { backgroundColor: ''blue'', childContent: [ Button(user.name) ] } } function UserList(users){ return users.map(eachUser => { button: UsernameButton(eachUser.name), listStyle: ''ordered'' }) } function App(appUsers) { return { pageTheme: redTheme, userList: UserList(appUsers) } }

Este ejemplo tiene cuatro capas de abstracción compuestas juntas.

Aplicación -> Lista de usuarios -> Botón de nombre de usuario -> Botón

Ahora, supongamos que para cualquiera de estos botones, necesito heredar el tema de color de cualquier máquina en la que se ejecute. Por ejemplo, los teléfonos móviles tienen texto en rojo, mientras que las computadoras portátiles tienen texto en azul.

Los datos del tema están en la primera abstracción (App). Necesita ser implementado en la última abstracción (Botón).

La forma molesta, sería pasar los datos del tema, de la aplicación al botón, modificando cada abstracción en el camino.

La aplicación pasa los datos del tema a UserList UserList lo pasa a UserButton UserButton lo pasa a Button

Se vuelve obvio que en bibliotecas grandes con cientos de capas de abstracción, esto es un gran dolor.

Una posible solución es transmitir el efecto a través de un controlador de efectos específico y dejar que continúe cuando sea necesario.

function PageThemeRequest() { return THEME_EFFECT; } function App(appUsers) { const themeHandler = raise new PageThemeRequest(continuation); return { pageTheme: themeHandler, userList: UserList(appUsers) } } // ...Abstractions in between... function Button(name) { try { return { buttonLabel: name, textColor: ''black'' }; } catch PageThemeRequest -> [, continuation] { continuation(); } }

Este tipo de manejo de efectos, donde una abstracción en una cadena puede suspender lo que está haciendo (implementación del tema), envía los datos necesarios al control central (App, que tiene acceso a la tematización externa) y transmite los datos necesarios para la continuación. Es un ejemplo extremadamente simplista de manejo de efectos algebraicamente .

Árbitro:

He buscado muchos enlaces, pero parece que nadie podría explicarlo específicamente. ¿Alguien podría dar algún código (usar javaScript) para explicarlo? ¡Muchas gracias!


Bueno, hasta donde entiendo el tema, los efectos algebraicos son actualmente un concepto académico / experimental que le permite alterar ciertos elementos computacionales (como llamadas a funciones, declaraciones impresas, etc.) llamados "efectos" mediante el uso de un mecanismo que se parece al throw catch

El ejemplo más simple que se me ocurre en un lenguaje como JavaScript es modificar el mensaje de salida en digamos console.log . Se supone que desea agregar "Mensaje de depuración:" delante de todas sus declaraciones de console.log por cualquier motivo. Esto sería un problema en JavaScript. Básicamente, deberías llamar a una función en cada console.log así:

function logTransform(msg) { return "Debug Message: " + msg; } console.log(logTransform("Hello world"));

Ahora, si tiene muchas declaraciones de console.log , cada una de ellas debe cambiarse si desea introducir el cambio en el registro. Ahora el concepto de efectos algebraicos le permitiría manejar el "efecto" de console.log en el sistema. Piense en ello como console.log lanzando una excepción antes de la invocación y esta excepción (el efecto) brota y puede ser manejada. La única diferencia es: si no se maneja, la ejecución continuará como si nada hubiera sucedido. No, lo que esto le permite hacer es manipular el comportamiento de console.log en un ámbito arbitrario (global o simplemente local) sin manipular la llamada real a console.log . Podría verse algo como esto:

try { console.log("Hello world"); } catch effect console.log(continuation, msg) { msg = "Debug message: " + msg; continuation(); }

Tenga en cuenta que esto no es JavaScript, solo estoy inventando la sintaxis. Como los efectos algebraicos son una construcción experimental, no están soportados de forma nativa en ningún lenguaje de programación importante que conozco (sin embargo, existen varios lenguajes experimentales como el eff https://www.eff-lang.org/learn/ ). Espero que tengas una comprensión aproximada de cómo está pensado que funcione mi código inventado. En el bloque try catch, el efecto que puede ser lanzado por console.log puede ser manejado. La continuación es una construcción tipo token que se necesita para controlar cuándo debe continuar el flujo de trabajo normal. No es necesario tener tal cosa, pero le permitiría realizar manipulaciones antes y después de console.log (por ejemplo, podría agregar un mensaje de registro adicional después de cada console.log)

En general, los efectos algebraicos son un concepto interesante que ayuda con muchos problemas del mundo real en la codificación, pero también puede presentar ciertos escollos si los métodos se comportan de manera diferente a lo esperado. Si quiere usar efectos algebraicos ahora mismo en JavaScript, tendría que escribir un marco para él y probablemente no podrá aplicar efectos algebraicos a funciones básicas como console.log todos modos. Básicamente, todo lo que puedes hacer ahora es explorar el concepto en una escala abstracta y pensar o aprender uno de los lenguajes experimentales. Creo que esa es también la razón por la que muchos de los artículos introductorios son tan abstractos.