7
votes

Meilleure façon de générer une fonction qui génère une fonction en C #

f # fournit une fonctionnalité où une fonction peut renvoyer une autre fonction.

Un exemple de fonction générant une fonction de F # est le suivant: P>

class Program
{
    delegate double PowerOf2(double exponent);
    delegate double PowerOf3(double exponent);
    delegate double PowerOfN(double n, double exponent);

    static void Main(string[] args)
    {
        PowerOfN powerOfN = (a, b) => { return Math.Pow(a,b) ; };
        PowerOf2 powerOf2 = (a) => { return powerOfN(2, a); };
        PowerOf3 powerOf3 = (a) => { return powerOfN(3, a); };

        double result = powerOf2(10);
        Console.WriteLine(result);
        result = powerOf3(10);
        Console.WriteLine(result);
    }
}


3 commentaires

Je n'ai jamais fait cela beaucoup de curry dans C #, mais pas Lambdas limite un peu l'utilité du currying? @Ngm; Quelle est votre raison pour générer des méthodes à la volée?


Aucune raison particulière, je voulais juste explorer comment cela pourrait être fait.


Notez que toutes les fonctions sont curreuses dans F #, afin que vous puissiez avoir écrit de manière équivalente powerfuncunlerator comme laissez PowerFunGenarator basenumber exponent = basenumber ** Exponent


4 Réponses :


3
votes

traduction presque littérale de votre original F # à c #: xxx


0 commentaires

6
votes

Vous pouvez écrire une fonction pour curry une autre fonction. L'inconvénient est que vous devriez créer toutes les surcharges dont vous avez besoin.

Exemple: P>

using System;

class Program {

    static Func<T2, TRes> Curry<T1, T2, TRes>(Func<T1, T2, TRes> f, T1 t1) {
        return (t2) => f(t1, t2);
    }

    static double PowerFunction(double d1, double d2) {
        return Math.Pow(d1, d2);
    }

    static void Main(string[] args) {
        var powerOf2 = Curry<double, double, double>(PowerFunction, 2);
        double r = powerOf2(3);
    }
}


1 commentaires

Je vais devoir explorer plus sur "Curry". Merci pour la réponse



10
votes

Bien sûr, c'est simple dans C #:

using System;
class P
{
  static void Main()
  {
      Func<double, Func<double, double>> powerFunctionGenerator = 
          baseNumber => exponent => Math.Pow(baseNumber, exponent);  

      Func<double, double> powerOfTwo = powerFunctionGenerator(2.0);
      Func<double, double> powerOfThree = powerFunctionGenerator(3.0);
      double power2 = powerOfTwo(10.0); 
      double power3 = powerOfThree(10.0);
      Console.WriteLine(power2); 
      Console.WriteLine(power3);
  }
}


4 commentaires

Vous pouvez également avoir la fonction comme paramètre: Func , Func > FunctionGenerator = (A, F) => B => F (A, B ); var powof2 = fonctionnelGenerator (2, PowerFunction);


Par curiosité, avez-vous déjà vu du code C # qui l'utilise pour résoudre une tâche pratique? J'ai écrit mon Curry / UNCRÉRY Fonctions en C #, mais on estime que la syntaxe serait trop déroutante ...


@Tomaspetricek: Bien sûr; Par exemple, j'ai une fois écrit une implémentation de l'algorithme A * pathfinant. L'algorithme en général nécessite une fonction qui peut estimer la distance entre deux points, mais pour toute exécution particulière de l'algorithme, il faut une fonction pouvant estimer la distance entre tout point et un point fixe. Vous pouvez utiliser une application partielle pour y parvenir.


@ Ericlippert qui sonne définitivement comme une belle application d'application partielle de fonction. La raison pour laquelle je ne suis pas trop convaincu de l'utiliser dans c # est qu'une déclaration comme point [] astar (point [], Func > métrique) est environ 70 caractères de long. Pas très netbook sympathique :-).



1
votes

Si ce que vous demandez, c'est comment réécrire PowerFunCenarator code> dans C #, vous pouvez le faire de manière assez simple:

let powerFunctionGenarator = fun baseNumber -> (fun exponent -> baseNumber ** exponent)


0 commentaires