2011-05-22 9 views
6

Supongamos que quiero poner en práctica una composición funcional, así:inferencia de tipos genéricos con la composición funcional

public Func<T,T> Compose<T>(Func<T,T> f, Func<T,T> g) 
    { 
     return new Func<T,T>(x => f(g(x))); 
    } 

Ahora bien, en la práctica, puedo utilizar este Componer() fn así:

public String ToUpper(String s) { return s.ToUpper(); }   
    public String Replicate(String s) { return s+s; } 

    public void Run() 
    { 
     var h = Compose<String>(ToUpper, Replicate); 
     System.Console.WriteLine("{0}", h("fred")); 
    } 

Y el resultado es FREDFRED.

¿Hay alguna manera de usar una sintaxis más simple para invocar a Compose? He intentado de esta manera:

 var h = Compose(ToUpper, Replicate); 

... pero me da un error de compilación:

error CS0411: The type arguments for method 'FunctionalTest.Compose(System.Func, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

bastante comprensible. Me pregunto si es posible declararlo de manera diferente y lograr que la inferencia funcione realmente.


EDITAR
El origen del problema: yo estaba viendo una charla en línea de un curso de licenciatura programación funcional, CS61A de la UC Berkley. (encuéntrelo en youtube). No tengo ningún entrenamiento formal en FP, y pensé que podría aprender algo. El programa de prof usa y él habla sobre cómo el esquema + ceceo son lenguajes puramente funcionales, y otros idiomas lo son menos. Específicamente identificó a Pascal, C, C++ y Java (pero no C#) como carentes de capacidades funcionales, y dijo que sería difícil hacer una composición funcional con estos idiomas ("Sin pararse en la cabeza"). Afirmó que un puntero a función (como disponible en C, C++) no es lo mismo que una función "entidad", una lambda. Lo entiendo.

Divertido - no mencionó Javascript o C#, que considero que son los principales lenguajes que tienen capacidades funcionales bastante buenas. (No sé F #.)

Me resulta curioso que esta sea una conferencia del año pasado - hace 14 meses - y sin embargo, parece desconocer los aspectos funcionales de los principales idiomas modernos.

Así que estoy siguiendo y haciendo ejercicios, pero en lugar de usar esquema o lisp, estoy usando C#. Y también haciendo algunos de ellos en Javascript.

De todos modos, gracias a todos por las respuestas de calidad.

+2

punta tangencial: se puede generalizar el método 'Compose' más como esto: http://paste.pocoo.org/show/393393/ – missingfaktor

+2

¿No funciona la composición tiene un tipo más general? 'Func Componer (Func f, Func g)' (traducido del Haskell '(.) :: (b -> c) -> (a -> b) -> a -> c'). –

Respuesta

4

El siguiente código funcionaría:

Func<string, string> toUpper = ToUpper; 
Func<string, string> replicate = Replicate; 

// now the compiler knows that the parameters are Func<string, string> 
var h = Compose(toUpper, replicate); 

Así que tal vez usted todavía puede obtener la mejora la legibilidad que está buscando mediante la definición de las variables sólo una vez y que la reutilización de ellos a través de sus pruebas (estoy suponiendo que esto es una utilidad de prueba ...)

+0

No es una utilidad de prueba específicamente, solo estoy "obteniendo funcional", eso es todo. He usado este tipo de cosas para los arneses de pruebas de rendimiento, pero esto es algo independiente. – Cheeso

2

También puede pasar Compose el parámetro, y realmente evaluar la función; debería ser capaz de inferir el tipo de parámetro en ese caso. (Sin embargo, es posible que necesite especificar el tipo de devolución.)

Aparte de eso, no, no hay forma de inferir cosas como esta en C#.

4

Me gusta la respuesta de Ran (+1), pero creo que esto lo hace un poco más conciso y agradable.(Programa para el supuesto de que usted tiene la posibilidad de redefinir las funciones de la siguiente manera.)

Func<string, string> toUpper = s => s.ToUpper(); 
Func<string, string> replicate = s => s + s; 

var h = Compose(toUpper, replicate); 
4

Agregando respuesta de lasseespeholt, si se define Componer como un método de extensión (renombrado "Entonces", por lo que el resultado tiene más sentido):

public static Func<T, T> Then<T>(this Func<T, T> f, Func<T, T> g) 
{ 
    return x => g(f(x)); 
} 

puede hacer que este fluidez:

var h = toUpper.Then(replicate); // .Then(trim) etc... 
+0

agradable ........... – Cheeso