2011-09-22 73 views
7

我想在C#中編寫一個簡單的Maybe monad。我希望能夠使用LINQ查詢語法。這就是我來了這麼遠:使用LINQ查詢語法與自定義Maybe monad實現

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實施?謝謝。

回答

8

的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); 
+0

[我不這麼認爲](http://ideone.com/2dQcN) – missingfaktor

+0

http://blogs.msdn.com/b/wesdyer/archive/2008/01/11/the -marvels-of-monads.aspx – onof

+0

我做了你所建議的改變。 [仍然不行]。(http://ideone.com/ofMKV) – missingfaktor