c# - C# 中的 Monadic 编程

标签 c# linq haskell functional-programming monads

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

从 do 符号翻译:

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)

据我所知,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# - C# 中的 Monadic 编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16254592/

相关文章:

c# - 比较两个列表并使用 linq 返回不匹配的项目

haskell - 种类多态元组

list - 用 '.' 将一个字符串切割成一个字符串列表

C# EF6 条件属性选择?

c# - 定期看到 ASP.NET 错误 CS0656 : Missing compiler required member

c# - 如何创建一个空的 SelectList

haskell - 是否有多种方法进行霍夫曼编码?

c# - C# 中的 2D 游戏编程教程

c# - DataGridViewCheckBoxColumn : FormatException on boolean-column

c# - List<object>.Contains 表达式树