2011-09-22 9 views
7

Estoy tratando de escribir una mónada Maybe simple en C#. Quiero poder usar la sintaxis de consulta LINQ con ella. Esto es lo que he encontrado hasta el momento:Uso de la sintaxis de consulta LINQ con la implementación personalizada de la mónada Maybe

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

Y este es el mensaje de error:

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 

Puede alguien por favor me guía sobre lo que debe hacer para poder utilizar la sintaxis de consulta con ¿Mi implementación Maybe? Gracias.

Respuesta

8

SelectMany necesidad debe ser declarada como una extensión de una clase estática, por ejemplo:

public static class Maybe { 

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

    ... 
} 

EDITAR:

que todavía necesitan una pieza. Con esto debería funcionar:

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

Esto es necesario porque:

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

se traduciría en:

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

lugar, por ejemplo:

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

se traduce en

aa.SelectMany(a => a); 
+0

[I no lo creo.] (Http://ideone.com/2dQcN) – missingfaktor

+0

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

+0

Hice el cambio que sugirió. [Todavía no funciona.] (Http://ideone.com/ofMKV) – missingfaktor

Cuestiones relacionadas