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 の on リストとSelectMany
C IEnumerable
# の on リストは同じ操作なので、このコードは問題なく動作するはずです。
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;
}
}))
};
}
}
しかし、うまくいきません。誰かがここで何が悪いのか教えてもらえますか?