Can I use mapWriterT instead of mapM/mapM_ (Haskell)?
mapWriterT is for transforming one WriterT into another. Its type is painfully generic, but allows you to transform pretty much everything about a WriterT.

mapWriterT :: (m (a, w) -&gt; n (b, w')) -&gt; WriterT w m a -&gt; WriterT w' n b


So if you start with a WriterT w m a, and you want to end up with WriterT w' n b (in other words, you can transform all 3 type parameters), then you have to provide a function of the form
m (a, w) -&gt; n (b, w').



Contrast this with mapM_ :: (a -&gt; m b) -&gt; [a] -&gt; m (). The purpose of this mapping is to take a list and perform monadic operations parameterized by the list's contents in sequential order.



While there may be a way to write your function in terms of mapWriterT, it is a completely different kind of mapping than mapM_, so your request to " replace mapM_ with mapWriterT" doesn't really make much sense to me. Nevertheless, let's give it a spin.

newtype MatchedFiles = MatchedFiles { unwrapFiles :: [FilePath] } deriving Monoid
newtype SubDirs = SubDirs { unwrapDirs :: [FilePath] }

filesInDir :: String -&gt; FilePath -&gt; WriterT MatchedFiles IO SubDirs
filesInDir s f = do
  d &lt;- liftIO $ listDir f
  let found = MatchedFiles $ filter (=~ s) (files d)
      subdirs = SubDirs $ subdirs d
  tell found
  return subdirs


OK, so here we've got a non-recursive WriterT that will simply tell the files that match the string at the given directory, and returns the subdirectories in that directory. I've used newtypes to help me not get the "found files" and "subdirectories" mixed up.

Now, what is the transformation we want to perform on this?

searchWriterT :: String -&gt; FilePath -&gt; WriterT MatchedFiles IO ()
searchWriterT s f = mapWriterT mapper (filesInDir s f)
  where
    mapper :: IO (SubDirs, MatchedFiles) -&gt; IO ((), MatchedFiles)
    mapper action = undefined


Assuming we want to write searchWriterT in terms of mapWriterT and filesInDir, I just followed the types and this is what we've got. Now, the question is, how to write mapper?

mapper action = do
  (SubDirs subdirs, files) &lt;- action
  if null subdirs
    then return ((), files)
    else undefined


Clearly, if there are no "subdirs", then we are done, and we simply regurgitate the files. But what if there are subdirs? Well, you've already figured out what to do: use mapM_ on the subdirs!

else runWriterT $ tell files &gt;&gt; mapM_ (searchWriterT s) subdirs


In fact, mapM_ will take care of the null case for us: it won't do anything in the event of an empty list.

mapper action = do
  (SubDirs subdirs, files) &lt;- action
  runWriterT $ tell files &gt;&gt; mapM_ (searchWriterT s) subdirs




Conclusion: mapWriterT felt kind of awkward for this problem, especially since inside the mapper we turned right around and used runWriterT. We didn't even get rid of mapM_, because mapM_ embodies exactly what needs to be done for this problem.

searchWriterT s f = filesInDir s f &gt;&gt;= mapM_ (searchWriterT s) . unwrapDirs