是否可以编写.NET的仿函数接口?

时间:2011-07-07 16:38:07

标签: .net functional-programming

功能语言通常具有Functor种类型/接口。

在.NET中,Functor接口是一个可由泛型类型(T<A>)实现的接口,它具有一个名为fmap的函数,它将函数从容器类型(A)转换为另一种类型( B)并返回容器类型为B的对象。

例如,类型List<A>将具有List.fmap方法。签名将类似于:

public List<B> fmap<B>(Func<A,B>);

是否可以创建这样的界面?有可能做类似的事情吗?是否有任何包提供这样的接口并为明显的类(List<T>Dictionary<A,B>Set<A>等提供扩展方法?)?

更新

我知道IEnumerable对象几乎可以做到这一点。关键的区别在于IEnumerable.Select返回的IEnumerable不是实现者的类型。例如,List.Select(A =&gt; B)返回IEnumerable而不是List。这说明为什么你不能以明显的方式为.NET实现IMappable,但是有没有可以用来有效实现它的hack或额外类型信息?

2 个答案:

答案 0 :(得分:2)

好的,基于评论,我怀疑答案是否定的 - 你需要更高阶的泛型类型。你想要的东西是:

// Not real syntax!
interface IFunctor<TFunctor<?>, TValue>
    where TFunctor<X> : IFunctor<TFunctor<X>, TValue>
{
    TFunctor<TProjection> Project<TProjection>(Func<TValue, TProjection> func);
}

问题是试图表达接口的实现必须以特定方式通用的想法,并允许在接口的其余部分使用该通用关系。我担心这不是.NET泛型的一部分。

Joe Duffy之前已经写过关于wishing for higher-order types的文章 - 遗憾的是我无法判断该文章是否相关,因为我现在无法理解。 (他的博客服务器有点临时,但内容很棒:)。


现在还不完全清楚,但基本上你可能只是谈论LINQ to Objects。例如:

var kids = people.Where(x => x.Age < 18) // Filtering
                 .Select(x => x.Name)    // Projection
                 .ToList();

您可以编写更通用的界面,例如

public interface IFunctor<T>
{
    IFunctor<TOther> Foo<TOther>(Func<T, TOther> selector);
}

...但是List<T>等实际上没有实现这样的接口.LINQ to Objects通过扩展方法工作。

答案 1 :(得分:2)

fmap类型的难度在于它是由更高级的类型变量(容器类型)参数化的。因此,除了简单的多态函数之外,例如列表上的map

map :: (a -> b) -> List a -> List b

fmap将此概括为适用于任何容器以及任何元素类型:

fmap :: Functor (f :: * -> *) => (a -> b) -> f a -> f b

C#中的问题是f是一个更高级的类型变量(它是一个类型函数)。想想,由于C#不支持更高级别的类型,所以你直接写这篇文章是不幸的。