The difficulty of giving a type to fmap
is that it is parameterized by a higher-kinded type variable, the container type. So beyond being a simple polymorphic function, like say, map
on lists:
map :: (a -> b) -> List a -> List b
fmap
generalizes this to work on any container, as well as any element type:
fmap :: Functor (f :: * -> *) => (a -> b) -> f a -> f b
The problem in C# is that f
is a higher-kinded type variable (it is a type function). Since C# doesn't support higher kinds, you'll be out of luck writing this directly, think.
Okay, based on the comment, I suspect the answer's no - you'd need higher-order generic types. You'd want something like:
// Not real syntax!
interface IFunctor<TFunctor<?>, TValue>
where TFunctor<X> : IFunctor<TFunctor<X>, TValue>
{
TFunctor<TProjection> Project<TProjection>(Func<TValue, TProjection> func);
}
The problem is trying to express the idea that the implementation of the interface must also be generic in a particular way, and allow that generic relationship to be used in the rest of the interface. That's not part of .NET generics, I'm afraid.
Joe Duffy has written about wishing for higher-order types before now - unfortunately I can't tell whether or not that article is relevant, as I can't get to it at the moment. (His blog server is somewhat temporamently, but the content is great :)
It's not entirely clear, but it's possible you're just talking about LINQ to Objects, basically. For example:
var kids = people.Where(x => x.Age < 18) // Filtering
.Select(x => x.Name) // Projection
.ToList();
You could write a more general purpose interface, e.g.
public interface IFunctor<T>
{
IFunctor<TOther> Foo<TOther>(Func<T, TOther> selector);
}
... but there's no such interface actually implemented by List<T>
etc. LINQ to Objects works via extension methods instead.