mis*_*tor 7 c# monads functional-programming
我想Maybe在C#中编写一个简单的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);
}
}
Run Code Online (Sandbox Code Playgroud)
这是错误消息:
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
Run Code Online (Sandbox Code Playgroud)
任何人都可以指导我如何使用查询语法与我的Maybe实现?谢谢.
必须将SelectMany 声明为静态类中的扩展名,例如:
public static class Maybe {
public static Maybe<B> SelectMany<B>(this Maybe<A> maybe, Func<A, Maybe<B>> f) {
return f(a);
}
...
}
Run Code Online (Sandbox Code Playgroud)
编辑:
你还需要一块.这应该工作:
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))));
}
Run Code Online (Sandbox Code Playgroud)
你需要这个因为:
from m0 in m
from n0 in n
select m0 + n0
Run Code Online (Sandbox Code Playgroud)
将翻译成:
m.SelectMany(m0 => n, (m, n0) => m0 + n0);
Run Code Online (Sandbox Code Playgroud)
相反,例如:
var aa = new List<List<string>>();
var bb = from a in aa
from b in a
select b;
Run Code Online (Sandbox Code Playgroud)
翻译成
aa.SelectMany(a => a);
Run Code Online (Sandbox Code Playgroud)