Function composition con Compose y AndThen en C#.

En este poste te voy a mostrar como puedes hacer composición de funciones en C#.

Primeros pasos.

La composición de funciones (function composition) es un mecanismo heredado del paradigma funcional que permite componer o encadenar una función a partir de otras.

Este mecanismo no es parte del framework, afortunadamente, puedes emularlo con métodos de extension y Funcs. C# soporta el uso de funciones como objetos desde hace tiempo.

Tienes dos opciones para evaluar la cadena, evaluar de izquierda a derecha, o viceversa:

  • Compose: C ⇒ B ⇒ A
  • AndThen: A ⇒ B ⇒ C

Cosas a tener en cuenta.

Este ejemplo solo evalúa funciones que tienen el mismo tipo de entrada y de salida, si necesitas resolver escenarios más complejos, quizá, te convenga descargar packages Nuget específicos como Language Extensions.

Ejemplo:

En el siguiente ejemplo hago uso de la composición de funciones al estilo de Scala. Con los métodos de extension Compose y AndThen. Descompuse la fórmula de cálculo del área del círculo en varias funciones, y las compuse para producir el resultado deseado.

using System;
Func<double, double> square = x =>
{
Console.WriteLine($"(A) Calculating square: {x}");
return x * x;
};
Func<double, double> multipliedByPi = x =>
{
Console.WriteLine($"(B) Multiplying by pi: {x}");
return x * 3.14;
};
Func<double, double> circleArea = multipliedByPi.Compose(square);
Func<double, double> anotherCircleArea = square.AndThen(multipliedByPi);
Console.WriteLine($"COMPOSE: Result of circleArea: {circleArea(10)}");
Console.WriteLine($"AND THEN: Result of anotherCircleArea: {anotherCircleArea(8)}");
//you can compose any function you want into a new one.
Console.WriteLine(circleArea.AndThen(x=>
{
Console.WriteLine("(C) Adding 1");
return x + 1;
}).Invoke(10));
internal static class CompositionExtensions
{
//AndThen A => B => C
public static Func<TA, TC> AndThen<TA, TB, TC>(this Func<TA, TB> left, Func<TB, TC> right) =>
x => right.Invoke(left.Invoke(x));
//Compose C => B => A
public static Func<TA, TC> Compose<TA, TB, TC>(this Func<TB, TC> left, Func<TA, TB> right) =>
x => left.Invoke(right(x));
}

Referencias:

 

Gustavo Sánchez

Soy especialista en escribir software de calidad. Mediante el uso de marcos de trabajo, técnicas y automatización de procesos he podido reducir los costes operativos de los sistemas de la empresa. Sistemas confiables y adaptables producen clientes felices.

Site Footer