Is there any way that I can generalise the type definitions here? Ideally, I'd like to be able to change the type of 'testInput' and have test correctly infer the type at compile time.
public static void Run()
{
var testInput = 3;
var test = ((Func<int, int>) Identity).Compose<int,int,int>(n => n)(testInput);
Console.WriteLine(test);
}
public static Func<T, V> Compose<T, U, V>(this Func<U, V> f, Func<T, U> g)
{
return x => f(g(x));
}
public static T Identity<T> (this T value)
{
return value;
}
Update: I can specify the type of the function passed into Compose but this still specifies the type in the line.
public static void Run()
{
var testInput = 3;
var identity = (Func<int, int>) Identity;
var test = identity.Compose((int n) => n)(testInput);
Console.WriteLine(test);
}
A little context; I'm working through Wes Dyer's The Marvel of Monads
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr. Stroustroupe.
C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.
C is more difficult to learn than JavaScript, but it's a valuable skill to have because most programming languages are actually implemented in C. This is because C is a “machine-level” language. So learning it will teach you how a computer works and will actually make learning new languages in the future easier.
Well seeing as I'm on a roll for spewing out text tonight I'll have my own stab at it. I should note that I am no expert on the C# compiler, I haven't read the specification (any of them... for anything), and although that article you linked was really interesting, I'd be lying if I said I was any sort of expert on that either (or even understood it all 100%).
Caveats aside, my take on your question is this:
Is there any way that I can generalise the type definitions here?
I think the short answer is no. With the information provided, there is simply not enough information for the type inference part of C#'s compiler to infer enough information from the usage of the various variables.
As the other answers here demonstrate, it can be simplified. You can use @Lee's IdentityFunc
to allow for type inference with var identity
. However, even with this addition, it is still not possible with your sample code to infer all the type variables of Compose
.
Imagine the following situation:
public static Func<T, V> Compose<T, U, V>(this Func<U, V> f, Func<T, U> g)
{
return x => f(g(x));
}
public static T Identity<T> (this T value)
{
return value;
}
public static Func<T, T> IdentityFunc<T>(this T value)
{
return (Func<T, T>)Identity;
}
and
public static void Run()
{
var a = 3; // a is int
var i = a.IdentityFunc(); // i is Func<int, int>;
var test = i.Compose(n => n)(a) // test is expected to be int
}
Initially this might appear as if test
should easily be inferred to int
. However, the return type of i.Compose
can only be inferred after the fact, from its usage. The C# compiler obviously won't allow this.
public static void Run()
{
var a = 3; // a is int
var i = a.IdentityFunc(); // i is Func<int, int>;
var c = i.Compose(n => n) // c is Func<T, int> - T cannot be resolved without knowledge of n
var test = c(a); // ideally have type inference infer c (Func<T, int>) as Func<int, int>
}
In that example, upon usage of c
with a
the compiler would have to retrospectively infer the return type of the call to i.Compose<T, U, V>(n => n)
to be Func<int, int>
. This is obviously not possible in the C# compiler. Take away the call c(a)
and the compiler would have no knowledge of the usage of c
, which would remove any possibility of inferring T
(not that it can anyway). It is possible a more advanced type inference system would be able to do this sort of inferring based on the usage of a generic return (possibly F# - another topic I'm no expert on).
As Wes Dyer doesn't provide specific usage of that particular example, it's unknown whether there is some other magic he uses to allow for the degree of type inference you're trying to achieve.
More qualified people like Eric Lippert would be able to provide you with a much greater level of detail (and technical accuracy / acuity). I read a great response he wrote on here to a question on type inference, but I can't find it. His blog has lots of great information. You could try contacting him if you're interested. Also, his answer to this question here discusses monads (and ultimately links back to Wes Dyer's article) buy you might be interested in reading it: Monad in plain English? (For the OOP programmer with no FP background)
You could write an extension method to return the Identity function for a type:
public static Func<T, T> IdentityFunc<T>(this T value)
{
return (Func<T, T>)Identity;
}
(or just return v => value;
)
Your test then becomes
var testInput = 3;
var identity = testInput.IdentityFunc();
test = identity.Compose((int n) => n)(testInput);
The closest I can get is to explicitly type the parameter for the n => n lambda:
var test = ((Func<int, int>)Identity).Compose((int n) => n)(testInput);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With