Haskell 一元滤波器与折叠的关系
许多高阶函数可以用Haskell 一元滤波器与折叠的关系,haskell,monads,fold,Haskell,Monads,Fold,许多高阶函数可以用折叠函数来定义。例如,这里是Haskell中filter和foldl之间的关系 myFilter p [] = [] myFilter p l = foldl (\y x -> if (p x) then (x:y) else y) [] (reverse l) 它们的一元版本filterM和foldM之间是否存在类似的关系?如何根据foldM编写filterM 我试图找到一个相当于\yx->if(px)then(x:y)else y的单子插入foldM,但没有成功。不
折叠
函数来定义。例如,这里是Haskell中filter
和foldl
之间的关系
myFilter p [] = []
myFilter p l = foldl (\y x -> if (p x) then (x:y) else y) [] (reverse l)
它们的一元版本filterM
和foldM
之间是否存在类似的关系?如何根据foldM
编写filterM
我试图找到一个相当于
\yx->if(px)then(x:y)else y
的单子插入foldM
,但没有成功。不确定它是否有任何意义(因为它有那种奇怪的反向
),但至少它的类型检查得很好:
myFilterM::Monad m=>(a->m Bool)->[a]->m[a]
myFilterM p l=foldM f[](反向l)
哪里
f y x=do
p1与D.M.的答案类似,只是没有反向
。让类型引导您:
import Control.Monad
{-
foldM :: (Monad m) => (b -> a -> m b) -> b -> [a] -> m b
filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
-}
filtM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
filtM p xs = foldM f id xs >>= (return . ($ []))
where
f acc x = do t <- p x
if t then return (acc.(x:)) else return acc
import-Control.Monad
{-
foldM::(单子m)=>(b->a->MB)->b->[a]->MB
filterM::(Monad m)=>(a->m Bool)->[a]->m[a]
-}
filtM::(单子m)=>(a->m布尔)->[a]->m[a]
filtM p xs=foldM f id xs>>=(返回($[]))
哪里
f acc x=do t是myFilter p[]=[]
冗余?@БММЙМААЛцББССССB--是的,绝对是。注意foldl
是这里的“错误”折叠,而foldr
是“正确”折叠。例如,对于无限列表,myFilter
是|
,而原始的filter
不是(好吧,假设谓词至少包含一个元素)。@MatveyAksenov yep,冗余的反向实际上是一个很好的症状,foldl
使用错误。@Aksenov。据我所知,Control.Monad
中没有foldrM
。欢迎您提供您自己的实现(无需使用反向
)作为答案,以及用foldrM
表示filterM
的代码。感谢您的回答。代码中的执行顺序有一个小问题,不知道为什么。这里有一个简单的测试。filterM(const[True,False])[1,2]=>[1,2],[1],[2],[2]。myFilterM(const[True,False])[1,2]=>[1,2],[2],[1],[]这是因为反向
。啊!现在我明白了。我必须liftM反转myfilterM
的结果,而不是反转l
,以获得标准执行顺序。现在一切都清楚了。