将 LINQ 查询语法与自定义 Maybe monad 实现结合使用

发布于 2024-12-06 02:12:38 字数 1717 浏览 1 评论 0原文

我正在尝试用 C# 编写一个简单的 Maybe monad。我希望能够使用 LINQ 查询语法。这是我到目前为止所想到的:

using System;
using System.Collections.Generic; 

abstract class Maybe<A> {
  public abstract Maybe<B> SelectMany<B>(Func<A, Maybe<B>> f);
  public abstract Maybe<B> Select<B>(Func<A, B> f);
}

class Just<A> : Maybe<A> {
  private readonly A a;

  public Just(A a) {
    this.a = a;
  }

  override public Maybe<B> SelectMany<B>(Func<A, Maybe<B>> f) {
    return f(a);
  }

  override public Maybe<B> Select<B>(Func<A, B> f) {
    return new Just<B>(f(a));
  }

  override public string ToString() {
    return "Just " + a;
  }
}

class Nothing<A> : Maybe<A> {
  override public Maybe<B> SelectMany<B>(Func<A, Maybe<B>> f) {
    return new Nothing<B>();
  }

  override public Maybe<B> Select<B>(Func<A, B> f) {
    return new Nothing<B>();
  }

  override public string ToString() {
    return "Nothing";
  }
}

static class Program {
  public static void Main(string[] args) {
    Maybe<int> m = new Just<int>(12);
    Maybe<int> n = new Nothing<int>();
    Maybe<int> result = from m0 in m
                        from n0 in n
                        select m0 + n0;
    Console.WriteLine(result);
  }
}

这是错误消息:

prog.cs(48,25): error CS1501: No overload for method `SelectMany' takes `2' arguments
prog.cs(5,28): (Location of the symbol related to previous error)
Compilation failed: 1 error(s), 0 warnings

任何人都可以指导我应该做什么才能在我的 Maybe 实现中使用查询语法吗?谢谢。

I am trying to write a simple Maybe monad in C#. I want to be able to use the LINQ query syntax with it. This is what I have come up with so far:

using System;
using System.Collections.Generic; 

abstract class Maybe<A> {
  public abstract Maybe<B> SelectMany<B>(Func<A, Maybe<B>> f);
  public abstract Maybe<B> Select<B>(Func<A, B> f);
}

class Just<A> : Maybe<A> {
  private readonly A a;

  public Just(A a) {
    this.a = a;
  }

  override public Maybe<B> SelectMany<B>(Func<A, Maybe<B>> f) {
    return f(a);
  }

  override public Maybe<B> Select<B>(Func<A, B> f) {
    return new Just<B>(f(a));
  }

  override public string ToString() {
    return "Just " + a;
  }
}

class Nothing<A> : Maybe<A> {
  override public Maybe<B> SelectMany<B>(Func<A, Maybe<B>> f) {
    return new Nothing<B>();
  }

  override public Maybe<B> Select<B>(Func<A, B> f) {
    return new Nothing<B>();
  }

  override public string ToString() {
    return "Nothing";
  }
}

static class Program {
  public static void Main(string[] args) {
    Maybe<int> m = new Just<int>(12);
    Maybe<int> n = new Nothing<int>();
    Maybe<int> result = from m0 in m
                        from n0 in n
                        select m0 + n0;
    Console.WriteLine(result);
  }
}

And this is the error message:

prog.cs(48,25): error CS1501: No overload for method `SelectMany' takes `2' arguments
prog.cs(5,28): (Location of the symbol related to previous error)
Compilation failed: 1 error(s), 0 warnings

Can anyone please guide me on what I should do to be able to use query syntax with my Maybe implementation? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

坚持沉默 2024-12-13 02:12:38

SelectMany must 应声明为静态类中的扩展,例如:

public static class Maybe {

   public static Maybe<B> SelectMany<B>(this Maybe<A> maybe, Func<A, Maybe<B>> f) {
       return f(a);
   }

   ...
}

编辑

您仍然需要一块。有了这个应该可以工作:

public static Maybe<V> SelectMany<T, U, V>(this Maybe<T> m, Func<T, Maybe<U>> k, Func<T, U, V> s)
{
  return m.SelectMany(x => k(x).SelectMany(y => new Just<V>(s(x, y))));
}

您需要这个,因为:

 from m0 in m
 from n0 in n
 select m0 + n0

将被翻译为:

 m.SelectMany(m0 => n, (m, n0) => m0 + n0);

相反,例如:

 var aa = new List<List<string>>();
 var bb = from a in aa
          from b in a
          select b;

被翻译为

 aa.SelectMany(a => a);

SelectMany must should be declared as an extension in a static class, for example:

public static class Maybe {

   public static Maybe<B> SelectMany<B>(this Maybe<A> maybe, Func<A, Maybe<B>> f) {
       return f(a);
   }

   ...
}

EDIT:

you still need a piece. With this should work:

public static Maybe<V> SelectMany<T, U, V>(this Maybe<T> m, Func<T, Maybe<U>> k, Func<T, U, V> s)
{
  return m.SelectMany(x => k(x).SelectMany(y => new Just<V>(s(x, y))));
}

You need this because:

 from m0 in m
 from n0 in n
 select m0 + n0

would be translated in:

 m.SelectMany(m0 => n, (m, n0) => m0 + n0);

Instead, for example:

 var aa = new List<List<string>>();
 var bb = from a in aa
          from b in a
          select b;

is translated in

 aa.SelectMany(a => a);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文