簡體   English   中英

C#中的Monadic編程

[英]Monadic Programming in C#

在Haskell中,我們有filterM函數。 它的源代碼是:

filterM          :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
filterM _ []     =  return []
filterM p (x:xs) =  do
flg <- p x
ys  <- filterM p xs
return (if flg then x:ys else ys)

從符號轉換:

filterM          :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
filterM _ []     =  return []
filterM p (x:xs) =  p x >>= \flg -> 
                    filterM p xs >>= \ys -> 
                    return(if flg then x:ys else ys)

據我所知, >>= on Haskell中的列表和C#中IEnumerable上的SelectMany是相同的操作,因此,這段代碼應該可以正常工作:

    public static IEnumerable<IEnumerable<A>> WhereM<A>(this IEnumerable<A> list, Func<A, IEnumerable<bool>> predicate)
    {
        // Like Haskells null
        if (list.Null())
        {
            return new List<List<A>> {new List<A>()};
        }
        else
        {
            var x = list.First();
            var xs = list.Tail(); // Like Haskells tail

            return new List<IEnumerable<A>>
                {
                    predicate(x).SelectMany(flg => xs.WhereM(predicate).SelectMany(ys =>
                        {
                            if (flg)
                            {
                                return (new List<A> {x}).Concat(ys);
                            }
                            else
                            {
                                return ys;
                            }
                        }))
                };
        }
    }

但它不起作用。 誰能指出我這里有什么問題?

我的C#有點生疏,但看起來你的基本情況是錯誤的。 當Haskell版本返回[[]] (包含空列表的列表)時,您將返回等效的[] (空列表)。

你的遞歸案例有同樣的問題。 例如,在else分支中,Haskell版本返回[ys]而您的版本返回ys 請記住,列表monad中的return會生成單個元素列表,而與C#中的return關鍵字無關。

看起來您的C#代碼相當於:

filterM          :: (a -> [Bool]) -> [a] -> [[a]]
filterM _ []     =  return []
filterM p (x:xs) = 
  return $
    p x >>= \flg -> 
    filterM p xs >>= \ys -> 
    if flg then x:ys else ys

return錯誤的地方。

我希望這樣的事情:

        return predicate(x).SelectMany(flg => 
            xs.WhereM(predicate).SelectMany(ys =>
                new List<IEnumerable<A>> { flg ? (new List<A> {x}).Concat(ys) : ys }))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM