不使用序列实现 mapM

Implement mapM without using sequence

我目前正在尝试解决 20 Intermediate Haskell Excercises 练习,但在不使用 sequence.

我只能通过简单地应用 fmap 生成 [m b],但我不知道如何继续:

moppy :: [a] -> (a -> m b) -> m [b]
moppy la f = furry' f la -- how do I transform [m b] to m [b] without sequence

谁能告诉我应该看哪个方向?

好吧,我不知道如何在不剧透的情况下做到这一点——所以这里有一个非常基本的/递归的定义:

moppy :: Monad m => [a] -> (a -> m b) -> m [b]
moppy [] _ = return []
moppy (x:xs) f = do
  y  <- f x
  ys <- moppy xs f
  return (y:ys)

它应该是不言自明的——请注意您需要 Monad m 约束(我认为您无论如何都需要它,因为没有它就变得相当不可能;))

当您开始仅使用 >>=return 实施 mapM 时,也许它会有所帮助。你最终会得到类似于:

mapM' :: Monad m => (a -> m b) -> [a] -> m [b]
mapM' _ []     = return []
mapM' f (x:xs) =        f x           >>=
                 \y  -> mapM' f xs    >>=
                 \ys -> return (y:ys)

这样就如上位发帖者所说给了你答案。您需要做的就是更改参数的顺序:

moppy :: (Misty m) => [a] -> (a -> m b) -> m [b]      
moppy []     _ = unicorn []
moppy (x:xs) f = banana (\y -> banana (\ys -> unicorn (y:ys)) (moppy xs f)) (f x)

或者:

moppy :: (Misty m) => [a] -> (a -> m b) -> m [b]      
moppy []     _ = unicorn []
moppy (x:xs) f = (\y  -> (\ys -> unicorn (y:ys)) `banana` moppy xs f) `banana` f x

或者:

moppy :: (Misty m) => [a] -> (a -> m b) -> m [b]      
moppy []     _ = unicorn []
moppy (x:xs) f = let g y = let h ys = unicorn (y : ys)
                            in h `banana` moppy xs f
                  in g `banana` f x 

在现代,正如本杰明霍奇森所说,我们应该使用 Applicative 来达到这个特定目的:

myMapM :: Applicative f
       => (a -> f b) -> [a] -> f [b]

我们希望 myMapM f []pure [](我们无法获得任何 b!),所以

myMapM f [] = pure []

现在我们进入问题的核心,找出递归步骤。我们要myMapM f (x : xs)执行f x,执行myMapM f xs,合并结果。所以

myMapM f [] = pure []
myMapM f (x : xs) = (:) <$> f x <*> myMapM f xs

当用列表做一些好的和有规律的事情时,我们经常可以只用 foldr:

myMapM f = foldr go (pure []) where
  go x r = (:) <$> f x <*> r

采取这种实施方式:

moppy :: Monad m => (a -> m b) -> [a] -> m [b]
moppy f xs = foldr g n xs 
  where
    n = return []
    g x mys = do {
      y  <- f x ;
      ys <- mys ;
      return (y:ys) }

(mys :: m [b] 因为 foldr g n (x:xs) = g x (foldr g n xs).)

(改编自 C9 讲座:Ralf Lämmel - Going Bananas [8 分 06 秒 - youtube)。