使用LINQ查询语法与自定义的Maybe单子实现

本文关键字:Maybe 实现 自定义 LINQ 查询 语法 使用 | 更新日期: 2023-09-27 18:09:33

我试图在c#中编写一个简单的Maybe单子。我希望能够使用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实现?谢谢。

使用LINQ查询语法与自定义的Maybe单子实现

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

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);