g ll =
foldlM (\ some_list b -> do
part <- f b
return (some_list ++ part)) [] ll
在上面的代码中,我使用do statement
只是因为f
函数返回monad类型:M a
其中a
是一个列表。
(我&#34;解包&#34;该列表包含<-
。这就是我需要do statement
)的原因。我可以避免它并更简洁地写出来吗? (是的,我知道我可以使用>>=
来编写它,但我也考虑更好的东西。)
答案 0 :(得分:6)
foldlM
是错误的工具。您可以使用它,作为chepner的答案显示,但是您连接列表的方式可能会变得昂贵。 Luka Rahne的单线优势更好:
g ll = fmap concat (mapM f ll)
另一种选择是直接使用foldr
:
g = foldr (\x r -> (++) <$> f x <*> r) (pure [])
通过内联foldr
:
g [] = pure []
g (x : xs) = (++) <$> f x <*> g xs
答案 1 :(得分:1)
您的do
表达式
do
part <- f b
return (some_list ++ part)
遵循fmap
捕获的提取 - 应用 - 返回模式(由于身份fmap f k = k >>= return . f
part
f b
(some_list ++)
应用于part
这可以通过fmap
:
-- foldlM (f b >>= return . (some_list ++)) [] ll
foldlM (\some_list b -> fmap (some_list ++) (f b)) [] ll