[Haskell-cafe] mixing map and mapM ?

Ben Millwood haskell at benmachine.co.uk
Thu May 6 07:09:22 EDT 2010


On Thu, May 6, 2010 at 11:51 AM, Bill Atkins <watkins at alum.rpi.edu> wrote:
> Almost - "liftM modificationTime" has type Status -> IO EpochTime.  Like
> other IO functions (getLine, putStrLn), it returns an IO action but accepts
> a pure value (the modification time)

ghci> :m +Control.Monad System.Posix.Files
ghci> :t liftM modificationTime
liftM modificationTime
  :: (Monad m) => m FileStatus -> m System.Posix.Types.EpochTime

where m = IO in this case.

> Also, I like this style:
> import Control.Applicative ((<$>))
> blah = do
>   times <- mapM (PF.modificationTime <$> PF.getFileStatus) filenames
>   ...
> The <$> operator evaluates to fmap so it's a cleaner way to apply a pure
> function to an IO value.

Usually I'd agree but in fact PF.getFileStatus is not an IO value, but
an IO function, so you need to map over its result:

mapM ((PF.modificationTime <$>) . PF.getFileStatus) filenames

but then you lose the convenience of the <$> as an infix operator, so

mapM (liftM PF.modificationTime . PF.getFileStatus) filenames

is probably clearer in this case. Or, if you're feeling particularly silly:

mapM (fmap fmap fmap modificationTime getFileStatus) filenames


More information about the Haskell-Cafe mailing list