如何在C#中创建类幺半群的接口?
我想要求实现接口(或从类派生)的东西包含如何在C#中创建类幺半群的接口?,c#,functional-programming,C#,Functional Programming,我想要求实现接口(或从类派生)的东西包含Aggregate的实现。也就是说,如果它们是T类型,我希望它们具有Func类型。在Haskell中,这被称为“幺半群” 编辑:我想称之为如下内容: list.Aggregate((x, accum) => accump.MAppend(x)); public interface IMonoid<T> { T Combine(T x, T y); T Identity { get; } } public static
Aggregate
的实现。也就是说,如果它们是T
类型,我希望它们具有Func
类型。在Haskell中,这被称为“幺半群”
编辑:我想称之为如下内容:
list.Aggregate((x, accum) => accump.MAppend(x));
public interface IMonoid<T>
{
T Combine(T x, T y);
T Identity { get; }
}
public static class Monoid
{
public static T Concat<T>(this IMonoid<T> m, IEnumerable<T> values)
{
return values.Aggregate(m.Identity, (acc, x) => m.Combine(acc, x));
}
}
var a = All.Instance.Concat(new[] { true, true, true });
根据DigalD的回答,这是我最好的尝试,但它无法编译:
interface IMonoid<T>
{
T MAppend(T other);
}
class Test
{
public static void runTest<T>(IEnumerable<IMonoid<T>> list)
{
// doesn't work
list.Aggregate((x, ac) => ac.MAppend(x));
}
}
接口IMonoid
{
T MAppend(T其他);
}
课堂测试
{
公共静态无效运行测试(IEnumerable列表)
{
//不起作用
聚合((x,ac)=>ac.MAppend(x));
}
}
您不应该让界面也通用吗
interface IMonoid<T>
{
public IMonoidHandler<T> handler {get;set;}
}
接口IMonoid
{
公共iMonodHandler处理程序{get;set;}
}
这个版本怎么样:
interface IMonoid<T>
{
T MAppend(IMonoid<T> other);
}
class Test
{
public static void runTest<T>(IEnumerable<IMonoid<T>> list)
where T : IMonoid<T>
{
list.Aggregate((x, ac) => ac.MAppend(x));
}
}
接口IMonoid
{
T MAppend(伊莫诺类其他);
}
课堂测试
{
公共静态无效运行测试(IEnumerable列表)
其中T:IMonoid
{
聚合((x,ac)=>ac.MAppend(x));
}
}
或者更好的办法是,从一开始就实施:
interface IMonoid<T>
where T : IMonoid<T>
{
T MAppend(IMonoid<T> other);
}
接口IMonoid
其中T:IMonoid
{
T MAppend(伊莫诺类其他);
}
幺半群是一个关联运算以及该运算的标识
interface Monoid<T> {
T MAppend(T t1, T t2);
T MEmpty
}
Apocalisp的答案看起来最接近实际情况,但我更喜欢这样:
list.Aggregate((x, accum) => accump.MAppend(x));
public interface IMonoid<T>
{
T Combine(T x, T y);
T Identity { get; }
}
public static class Monoid
{
public static T Concat<T>(this IMonoid<T> m, IEnumerable<T> values)
{
return values.Aggregate(m.Identity, (acc, x) => m.Combine(acc, x));
}
}
var a = All.Instance.Concat(new[] { true, true, true });
在这里,我完全武断地、前后不一致地决定使用Haskell的命名,因此我将方法命名为Concat
正如我在我的文章中所描述的,人们总是必须从单倍体恒等式开始累加,在这种情况下m.identity
正如我在文章中所描述的,您可以使用Aggregate
扩展方法,而不是强制for
循环,但是您必须使用带有初始种子值的重载。该种子值为m.Identity
现在可以定义各种幺半群,例如Sum
:
public class Sum : IMonoid<int>
{
public int Combine(int x, int y)
{
return x + y;
}
public int Identity
{
get { return 0; }
}
}
由于我将幺半群参数设置为Concat
方法的this
参数,因此该方法扩展了IMonoid
接口,而不是IEnumerable
。我认为这提供了一个更可读的API。例如:
var s = new Sum().Concat(new[] { 1000, 300, 30, 7 });
产生s==1337
,而
var p = new Product().Concat(new[] { 2, 3, 7 });
产生p==42
如果您不喜欢每次都必须创建一个new Sum()
或new Product()
对象,您可以创建您的幺半群,如下All
monoid:
public class All : IMonoid<bool>
{
public static All Instance = new All();
private All() { }
public bool Combine(bool x, bool y)
{
return x && y;
}
public bool Identity
{
get { return true; }
}
}
这里,a
是true
。您可以以相同的方式使用类似编写的任意幺半群:
var a = Any.Instance.Concat(new[] { false, true, false });
我将把它留作练习,让读者了解如何实现任何。您能看到我的编辑吗?我认为我不能按照你建议的方式来做,因为我无法正确调用list.Aggregate
。聚合是指折叠?删除“public”关键字,接口将编译。如果没有,请发布更多代码…迭戈:是的,大多数语言都称之为“折叠”。不知道为什么C#与“聚合”一起出现@大卫:我更新了代码-这不是问题所在。是的,这是个好主意,但是如果接口是这样指定的,那么这些应该是静态方法。不,它们实际上是实例方法。T
和Monoid
是不同的对象,但是这个代码不能总结整数列表。最好不要为此使用接口:publicstatictsum(这个IEnumerable summables,tzero,funcadd){return summables.Aggregate(zero,add);}
它绝对可以对整数列表求和。您只需要一个幺半群
,编写起来很简单。