A better way to map a function that requires IO over a list

前端 未结 4 1470
感动是毒
感动是毒 2021-01-20 03:40

So lately I have a list of strings, and need to independently go over each one and perform some IO function.

So basically what I have is this:

4条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-20 04:16

    First, easy improvement:

    goOverList' :: [String] -> IO ()
    goOverList' []     = return ()
    goOverList' (x:xs) = do
        putStrLn x
        goOverList' xs
    

    The base case for recursion should be the empty list: in that case, you simply return the IO action return () which does nothing. When you have one or more elements, you print it and continue with the rest of the list, simple as that.

    The same exact thing is achievable in a way more compact definition with mapM_ :: Monad m => (a -> m b) -> [a] -> m (): it is the same as the regular map, except that it works with monadic actions. Instead of returning the collection of results m [b] like the regular mapM would do, it throws it away. It works just fine for you in this case, as you're are only interested in printing out the elements of he list.

    goOverList'' :: [String] -> IO ()
    goOverList'' = mapM_ putStrLn
    

    In order to be even more general, we could rely on print :: Show a => a -> IO () instead of putStrLn and accept in input every list of "showable" items:

    goOverList''' :: (Show a) => [a] -> IO ()
    goOverList''' = mapM_ print
    
    data T = One | Two | Three deriving (Show)
    
    main = do
        let myList = [One, Two, Three]
        goOverList''' myList
    

提交回复
热议问题