更惯用的提前退出 mapM 的方式

More idiomatic way of exiting mapM early

给定 returns m (Maybe a) 的操作列表,我正在尝试 return m (Maybe [a]) 如果任何单个结果是 Nothing整个结果是Nothingm 包含 StateT,我想避免 运行 在第一个 Nothing 被 return 编辑后执行任何操作。

尝试使用 mapM,然后将 Maybe 移到列表之外会导致所有操作 运行。

我有这个解决方案,但只有大量包装和展开的嵌套 case 语句让我觉得可能有更优雅的方法来执行此操作。通常当我有这种感觉时,会有一个更通用类型的单行线,它做的事情完全一样。

有什么建议吗?

myMapM' :: Monad m => (t1 -> m (Maybe t)) -> [t1] -> m (Maybe [t])
myMapM' f [] = return (Just [])
myMapM' f (a:as) = do
  r <- f a 
  case r of
    Nothing -> return Nothing
    Just g -> do
      rs <- myMapM' f as
      case rs of
        Nothing -> return Nothing
        Just gs -> return (Just (g:gs))

您想要的行为是 the monad transformer MaybeT

myMapM :: Monad m => (t1 -> m (Maybe t)) -> [t1] -> m (Maybe [t])
myMapM f = runMaybeT . mapM (MaybeT . f)