避免在foldM中使用do语句

时间:2016-12-19 13:03:19

标签: haskell

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)的原因。我可以避免它并更简洁地写出来吗? (是的,我知道我可以使用>>=来编写它,但我也考虑更好的东西。)

2 个答案:

答案 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

  1. 您从计算part
  2. 中提取f b
  3. 您将(some_list ++)应用于part
  4. 您将返回该应用程序的结果。
  5. 这可以通过fmap

    一步完成
    -- foldlM (f b >>= return . (some_list ++)) [] ll
    foldlM (\some_list b -> fmap (some_list ++) (f b)) [] ll
    
相关问题