功能语言通常具有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或额外类型信息?
答案 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#不支持更高级别的类型,所以你直接写这篇文章是不幸的。