Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中创建类幺半群的接口?_C#_Functional Programming - Fatal编程技术网

如何在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);}
它绝对可以对整数列表求和。您只需要一个
幺半群
,编写起来很简单。