DEV Community

Heiker
Heiker

Posted on Edited on Originally published at vonheikemen.github.io

ÂŋQuÃĐ son los applicative functors?

Nuestra agenda para hoy serÃĄ aprender quÃĐ son applicative functors (aplicativos de ahora en adelante) usando javascript. Sí, usaremos javascript. No me juzguen, es lo que sÃĐ. Al terminar este artículo sabrÃĄn cÃģmo crearlos, cÃģmo reconocerlos y les enseÃąarÃĐ un truco que puede o no resultarles Útil alguna vez.

Bien, empecemos desde el principio.

ÂŋQuÃĐ es un functor?

Desde un punto de vista "tÃĐcnico" podemos decir que son un tipo de contenedor. VerÃĄn, la manera mÃĄs fÃĄcil de implementar un functor es "envolviendo" un valor dentro de una estructura. Para interactuar con el valor dentro del functor se provee un mÃĐtodo normalmente llamado map, este nos permite transformar el valor usando una funciÃģn (un callback) y luego envuelve el nuevo valor otra vez en una estructura del mismo tipo.

Veamos quÃĐ puede hacer map. Para familiarizarnos con este tipo de estructuras voy a demostrar sus capacidades usando un tipo de dato comÚn en javascript, los arreglos.

const numbers = [1];
const plus_one = (number) => number + 1;

numbers.map(plus_one);
// [ 2 ]
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

ÂŋQuÃĐ pasa aquí?

Tenemos un nÚmero dentro de un arreglo, luego usamos map para acceder a ÃĐl y transformarlo usando una funciÃģn, y despuÃĐs el nuevo valor que obtenemos es puesto nuevamente en un arreglo. Eso es todo. Eso es bÃĄsicamente el comportamiento que debe tener un functor.

Ahora bien, los arreglos no son los Únicos que siguen este patrÃģn, en javascript tenemos otra estructura que actÚa de la misma manera, la clase Promise. Con las promesas no tenemos un mÃĐtodo map pero tenemos uno llamado then, no son exactamente iguales en cuestiÃģn de comportamiento pero se acerca lo suficiente.

const number = Promise.resolve(1);
const plus_one = (number) => number + 1;

number.then(plus_one);
// Promise { <state>: "pending" }
// 2
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Aquí ocurre la misma cosa, tenemos un valor dentro de una estructura (una promesa), tenemos un mÃĐtodo que nos da acceso al valor (then) y finalmente el nuevo valor queda atrapado en una nueva instancia de la misma estructura.

Y ese es el patrÃģn. Ya hemos cubierto todo lo que necesitamos saber sobre los functors por ahora. Si desean saber mÃĄs detalles sobre ellos revisen este artículo: El Poder de Map.

ÂŋListos para seguir?

Applicatives

Resulta que los aplicativos son functors con características extras. Ellos nos dan la habilidad de mezclar dos functors. Específicamente, nos permiten aplicar una funciÃģn dentro de un functor a un valor que tambiÃĐn esta dentro de un functor.

Espera... ÂŋquÃĐ? ÂŋUna funciÃģn dentro de un functor?

Sí. Algo así.

const plus_one = (number) => number + 1;

// Y luego

[plus_one];

// Ó

Promise.resolve(plus_one);
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

ÂŋPor quÃĐ alguien haría eso?

Buena pregunta. La respuesta, nadie lo haría. Si hablamos de patrones comunes en javascript este no es uno de ellos. Eso no significa que los aplicativos no tenga un uso.

Volviendo a nuestra definiciÃģn. Normalmente, si tenemos un valor y una funciÃģn somos capaces de aplicar dicha funciÃģn así: una_funciÃģn(un_valor). Eso no funcionaría si ambos estÃĄn encerrados dentro de una estructura. Para "arreglar" eso, los aplicativos tienen un mÃĐtodo llamado ap (apply abreviado) que se encarga de sacar la funciÃģn y el valor de sus respectivas estructuras y aplicar la funciÃģn.

Y es en este punto que me gustaría mostrarles un ejemplo de un tipo de dato que ya sigue las reglas de los aplicativos pero no se me ocurre ninguno. Pero no teman, tomemos esto como una oportunidad para hacer algo mÃĄs.

Crear un Aplicativo desde cero

Para no complicarnos mucho lo que haremos serÃĄ crear una pequeÃąa extensiÃģn de la clase Promise. Vamos a hacer que una promesa se comporte mÃĄs como un functor aplicativo.

ÂŋPor donde comenzamos?

  • La meta

Lo que queremos hacer es retrasar ejecuciÃģn de una promesa. Normalmente cuando se crea una promesa esta ejecuta la "tarea" asignada inmediatamente pero no queremos eso, esta vez queremos controlar cuando se ejecuta la tarea. Para lograr nuestro objetivo crearemos un mÃĐtodo llamado fork, este se encargarÃĄ de crear la promesa y preparar las funciones en caso de ÃĐxito y error.

function Task(proc) {
  return {
    fork(err, success) {
      const promise = new Promise(proc);
      return promise.then(success).catch(err);
    }
  }
}
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Genial. Ahora vamos comparar esto con una promesa normal.

let number = 0;
const procedure = function(resolve, reject) {
  const look_ma = () => {
    console.log(`IT WORKED ${++number} times`);
    resolve();
  };

  setTimeout(look_ma, 1000);
};

new Promise(procedure); // Esta se ejecuta inmediatamente

Task(procedure); // Esta no hace nada
Task(procedure)  // Esta sí
  .fork(
    () => console.error('AAHHH!'),
    () => console.log('AWW')
  );
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Si ejecutan ese cÃģdigo deberían ver estos mensajes despuÃĐs de 1 segundo.

IT WORKED 1 times
IT WORKED 2 times
AWW
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Ahora que tenemos lo que queremos vamos al siguiente paso.

  • Haz un functor

Como ya saben los aplicativos son functors, significa que ahora necesitamos un mÃĐtodo map.

Repasemos una vez mÃĄs. ÂŋCuÃĄl es el comportamiento que esperamos de map?

  1. Debería darnos acceso al valor almacenado internamente a travÃĐs de una funciÃģn.
  2. Debería retornar un nuevo contenedor del mismo tipo. En nuestro caso una nueva instancia de Task.
  function Task(proc) {
    return {
+     map(fn) {
+       return Task(function(resolve, reject) {
+         const promise = new Promise(proc);
+         promise.then(fn).then(resolve).catch(reject);
+       });
+     },
      fork(err, success) {
        const promise = new Promise(proc);
        return promise.then(success).catch(err);
      }
    }
  }
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

ÂŋQuÃĐ pasa en map? Bueno, primero recibimos el argumento fn esa serÃĄ una funciÃģn. Luego, retornamos una instancia de Task. Dentro de esa nueva instancia construimos la promesa justo como hacemos en fork pero esta vez es mÃĄs "seguro" porque no se ejecutarÃĄ inmediatamente. El siguiente paso es colocar las funciones que requiere promise en su respectivo orden, primero fn la cual transformarÃĄ el valor, luego resolve que marca el "fin" de la tarea actual y finalmente catch que recibirÃĄ la funciÃģn reject de la tarea actual.

Podemos probar lo que tenemos hasta ahora.

const exclaim = (str) => str + '!!';
const ohh = (value) => (console.log('OOHH'), value);

Task((resolve) => resolve('hello'))
  .map(exclaim)
  .map(ohh)
  .fork(console.error, console.log);
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Si ejecutan eso tal cual como esta deberían ver esto.

OOHH
hello!!
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Pero si eliminan fork deberían tener esto.

ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Sí, así es, deberían tener absolutamente nada. Ya hemos terminado con el patrÃģn functor de nuestro Task.

  • Vamos por Apply

Ya estamos a medio camino. Lo que haremos ahora serÃĄ que crear ap.

Como yo lo veo ap es map pero con un giro en la trama: la funciÃģn que queremos aplicar estÃĄ dentro de una instancia de Task [mÚsica dramÃĄtica suena en el fondo].

Con esa idea en la mente podemos implementar ap.

  function Task(proc) {
    return {
      map(fn) {
        return Task(function(resolve, reject) {
          const promise = new Promise(proc);
          promise.then(fn).then(resolve).catch(reject);
        });
      },
+     ap(Fn) {
+       return Task(function(resolve, reject) {
+         const promise = new Promise(proc);
+         const success = fn => promise.then(fn);
+         Fn.fork(reject, success).then(resolve);
+       });
+     },
      fork(err, success) {
        const promise = new Promise(proc);
        return promise.then(success).catch(err);
      }
    }
  }
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

ÂŋNotan la diferencia con map? No se preocupen igual les dirÃĐ, la diferencia es que para aplicar la funciÃģn en Fn usamos fork en lugar de interactuar con una promesa normal. Eso es todo. Veamos si funciona.

const to_uppercase = (str) => str.toUpperCase();
const exclaim = (str) => str + '!!';

const Uppercase = Task((resolve) => resolve(to_uppercase));
const Exclaim = Task((resolve) => resolve(exclaim));
const Hello = Task((resolve) => resolve('hello'));

Hello.ap(Uppercase).ap(Exclaim)
  .fork(console.error, console.log);
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

ÂĄLo logramos! Ahora podemos mezclar funciones que se encuentren dentro de aplicativos. Pero Task aÚn no puede entrar en el club de los aplicativos. Tenemos que ocuparnos de otra cosa primero.

  • El ingrediente olvidado

Los aplicativos deben ser capaces de colocar cualquier valor dentro de la unidad mÃĄs simple de su estructura.

La clase Promise tiene algo así. En lugar de hacer esto.

new Promise((resolve) => resolve('hello'));
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Usualmente hacemos esto.

Promise.resolve('hello');
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Luego de usar Promise.resolve podemos empezar a usar mÃĐtodos como then y catch. Eso es lo que le hace falta a nuestro Task.

Para esta implementar esto necesitaremos un mÃĐtodo estÃĄtico. Para esto existen varios nombres, algunos lo llaman "pure" otros lo llaman "unit" y tambiÃĐn estÃĄn quienes lo llaman "of".

Task.of = function(value) {
  return Task((resolve) => resolve(value));
};
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Y ahora sí, finalmente podemos decir que tenemos un aplicativo.

Algo que puedes usar en tu desarrollo diario

Poder crear tu propio tipo de dato es genial, Âŋpero no sería mejor si pudiÃĐramos aplicar estos patrones con las estructuras que ya existen?

Tengo buenas y malas noticias. La buena es que definitivamente podemos. La mala es que a veces puede ser incÃģmodo.

Sigamos con el ejemplo de Task que hemos usado hasta ahora. Pero ahora digamos que queremos usar map y ap pero no queremos crear una nueva estructura. ÂŋQuÃĐ hacemos? Un par de funciones serÃĄn suficientes.

Si ya estÃĄn familiarizados con los patrones que buscan, escribirlos en unas funciones estÃĄticas bastarÃĄ. Así luciría nuestro Task como funciones simples.

const Task = {
  of(value) {
    return Promise.resolve(value);
  },
  map(fn, data) {
    return data.then(fn);
  },
  ap(Fn, data) {
    return Fn.then(fn => data.then(value => fn(value)));
  }
};
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Para usar map sería así.

const to_uppercase = (str) => str.toUpperCase();

Task.map(to_uppercase, Task.of('hello'))
  .then(console.log);
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Y ap funciona de la misma manera.

const exclaim = (str) => str + '!!';

Task.ap(Task.of(exclaim), Task.of('hello'))
  .then(console.log);
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Puedo percibir su escepticismo desde aquí. Sean pacientes. Ahora, map parece medio Útil pero ap no tanto. No se preocupen, aÚn podemos usar ap para un bien mayor. ÂŋY si les digo que podemos tener una versiÃģn "mejorada" de map? Nuestro map sÃģlo trabaja con funciones que reciben un argumento y eso es bueno pero puede haber ocasiones en que necesitemos mÃĄs que eso.

Digamos que tenemos una funciÃģn que recibe dos argumentos pero en su mayoría los argumentos casi siempre vienen de dos promesas diferentes. Así que, en nuestra situaciÃģn imaginaria tenemos estas funciones.

function get_username() {
  return new Promise((resolve) => {
    const fetch_data = () => resolve('john doe'); 
    setTimeout(fetch_data, 1000);
  });
}

function get_location() {
  return new Promise((resolve) => {
    const fetch_data = () => resolve('some place'); 
    setTimeout(fetch_data, 500);
  });
}

function format_message(name, place) {
  return `name: ${name} | place: ${place}`;
}
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Cuando usamos format_message sus argumentos vienen de las otras dos funciones get_username y get_location. Esas Últimas dos son asíncronas, entonces tal vez se vean tentados a usar las palabras clave Async/Await pero esa no sería una buena idea. VerÃĄn, esas funciones no depende la una de la otra, estaríamos desperdiciando tiempo si hacemos que se ejecuten en secuencia cuando deberían ejecutarse de manera concurrente. Una soluciÃģn puede encontrarse en la forma de Promise.all y se ve así.

Promise.all([get_username(), get_location()])
  .then(([name, place]) => format_message(name, place))
  .then(console.log);
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Ahí lo tienen. Eso funciona. Pero nosotros podemos hacer algo mejor, ya que tenemos los aplicativos de nuestro lado. AdemÃĄs, ya tenemos ese objeto Task. Ahora sÃģlo vamos a agregar una funciÃģn mÃĄs, esta harÃĄ lo mismo que estÃĄ haciendo Promise.all.

Task.liftA2 = function(fn, A1, A2) {
  const curried = a => b => fn(a, b);
  return Task.ap(Task.map(curried, A1), A2);
};
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

Ya les explico el nombre despuÃĐs. Ahora veamos cÃģmo se usa.

Task.liftA2(format_message, get_username(), get_location())
  .then(console.log);
ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”

ÂŋNo les parece que esto es un poco mejor?

Y sí, es cierto que pueden presentar argumentos contra la implementaciÃģn de liftA2 e incluso todo el objeto Task, pero todos los patrones que he mostrado aquí deberían funcionar para los aplicativos que puedan encontrarse por ahí.

Como un ejercicio pueden intentar implementar map y ap para la clase Set. Vean que clase de cosas graciosas descubren en el proceso.

En fin, el nombre liftA2. En el paradigma funcional cuando logramos que una funciÃģn trabaje con un tipo de contenedor como lo son los functors se dice que "levantamos" (lift en inglÃĐs) esa funciÃģn al contexto de ese contenedor. ÂŋQuÃĐ significa eso de contexto? Bueno, en el mundo de los arreglos la funciÃģn que le proveen a map puede ejecutarse muchas veces (o ninguna), en el contexto de una promesa la funciÃģn que suministran a then sÃģlo se ejecuta cuando la promesa culmina su tarea de manera exitosa. ÂŋYa ven lo que digo? Bien. ÂŋY el A2? Ya saben, es porque recibe sÃģlo dos argumentos.

Hay otro truco que se puede hacer con los aplicativos pero aÚn no entiendo completamente cÃģmo funciona así que serÃĄ en otra ocasiÃģn.

ConclusiÃģn

ÂŋQuÃĐ aprendimos hoy, clase?

  • Aprendimos de los functors:
    • QuÃĐ hacen.
    • QuÃĐ patrones deben seguir.
  • Aprendimos de los aplicativos
    • QuÃĐ son.
    • QuÃĐ hacen.
    • CÃģmo crear uno desde cero.
    • CÃģmo hacer un mÃĐtodo ap aÚn si la estructura con la trabajamos no tiene soporte para el patrÃģn de los aplicativos.
    • Y esa cosa liftA2 que se ve genial.

ÂŋAprendieron todo eso? Dios santo. Ustedes son los mejores.

Bueno, mi trabajo aquí ha terminado.

Fuentes


Gracias por su tiempo. Si este artículo les pareciÃģ Útil y quieren apoyar mis esfuerzos para crear mÃĄs contenido pueden dejar una propina en ko-fi.com/vonheikemen.

buy me a coffee

Top comments (4)

ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
cescquintero profile image
Francisco Quintero ðŸ‡ĻðŸ‡ī •

Un tema super avanzado e interesante el que acabo de leer. Ahora, este tipo de patrÃģn se vuelve un tanto esotÃĐrico de usar, Âŋno crees? Para jugar y aprender estÃĄ bien pero en el día a día, toca usar lo normalito 😅

Muy buen artículo!

ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
vonheikemen profile image
Heiker • • Edited

Ahora, este tipo de patrÃģn se vuelve un tanto esotÃĐrico de usar, Âŋno crees?

Concuerdo.

Lo que pasa es que los aplicativos resuelven un problema que sÃģlo te encuentras si utilizas los functors con mucha frecuencia. En nuestro día a día, en el mejor de los casos, los utilizamos de manera trivial. Si la comunidad de javascript comenzara a adoptar patrones como los que yo describo aquí: tÃĐcnicas de composiciÃģn, tarde o temprano tendrían que acudir a cosas como los aplicativos.

ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ”
 
cescquintero profile image
Francisco Quintero ðŸ‡ĻðŸ‡ī •

Cierto. Me hace recordar a los bloques en Ruby.

Los bloques son una forma de ejecutar cÃģdigo en medio de otra ejecuciÃģn. Un ejemplo muy pobre sería algo como:

EJECUCIÓN NORMAL
-> cÃģdigo del bloque
EJECUCIÓN NORMAL

Y hay un montÃģn de artículos explicando bloques, procs y lambdas (cosas similares) pero en realidad el caso de uso es tan específico que muchos devs Ruby no usan bloques cuando escriben cÃģdigo.

Terminamos usando los bloques en DSLs de gemas o funciones de la librería estÃĄndar del lenguaje 😄

Puede que este tema que explicas de functors viva algo similar. En el día a día no tiene tanto uso pero en librerías de terceros donde hay muchas abstracciones, seguro tendrÃĄn mÃĄs cabida.

ðŸ”ī Hot News: vonheikemen/que son los applicative functors cnn - āļŠāļĢāļļāļ›āļ”āļĢāļēāļĄāđˆāļēāļĨāđˆāļēāļŠāļļāļ” Thread
 
vonheikemen profile image
Heiker •

Puede que este tema que explicas de functors viva algo similar. En el día a día no tiene tanto uso pero en librerías de terceros donde hay muchas abstracciones, seguro tendrÃĄn mÃĄs cabida.

No del todo. Este patrÃģn de los functors puede ser Útil en muchas situaciones. Algunos lenguajes compilados de tipado fuerte los han adoptado para resolver problemas como los valores ausentes o el manejo de errores. Nosotros los que nos ganamos la vida con lenguajes dinÃĄmicos (javascript, ruby, python, etc...) simplemente aprendimos a vivir sin ellos.