I am working my way through the Haskell Book and ran into the exercises at the end of the Monad chapter(18). One in particular asked to define a function with the following signature:
meh :: Monad m => [a] -> (a -> m b) -> m [b]
So I did. I found this routine difficult to implement at first, but once I understood what I was doing and what I needed to do a little better I figured it out.
I have three versions of the routine, my first attempt, a slightly refactored attempt, and a final attempt using do-notation. I was wondering if anyone can give advice on how I could potentially refactor this routine further, or how I can make my implementation better. I feel like I can make the routine far cleaner than I have it, but I am not sure how.
WARNING: If you are reading the Haskell Book and want to work through the exercises yourself, I recommend you do not read any further
Here are all three implementations
-- Attempt #1 with helper routine meh :: Monad m => [a] -> (a -> m b) -> m [b] meh list fn = doWork list (return $ ) fn where doWork (x:xs) base f | length xs == 0 = (addToMonad x base f) >>= (\x -> return $ reverse x) | otherwise = doWork xs (addToMonad x base f) f addToMonad x baseMonad fn = do someVal <- (fn x) base <- baseMonad return $ someVal:base -- Attempt #2 with a fold meh' :: Monad m => [a] -> (a -> m b) -> m [b] meh' list fn = (foldl (\acc x -> (fn x) >>= (\y -> acc >>= (\z -> return $ y:z))) (return $ ) list) >>= (\x -> return $ reverse x) -- Attempt #3 with a fold and do-notation mehDo :: Monad m => [a] -> (a -> m b) -> m [b] mehDo list fn = do final <- (foldl (\acc x -> do val <- (fn x) mList <- acc return $ val:mList) (return $ ) list) return $ reverse final
I want to say my last implementation is the easiest to read (it would be easier with better names, IMO) but I don't really know that it is. I am not super experienced in the ways of Haskell, so to be frank I read the routines really slowly regardless.
Anyway, advice or tips on how to make this cleaner would be much appreciated.