Yep, you and Ben are both correct.  Mea culpa and sorry for the bad answer.

Just curious: why does getModificationTime take an IO FileStatus rather than a FileStatus?

On Thu, May 6, 2010 at 7:00 AM, Neil Brown <nccb2@kent.ac.uk> wrote:
Bill Atkins 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)

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.
That won't type-check (unless I've missed some crafty trick with the types?!); you have two functions you want to compose, but the <$> operator (i.e. fmap) applies a function on the left to a functor-value on the right.  You would instead need:


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

At which point I prefer Ivan's liftM version rather than the above section (or worse: using (<$>) prefix).  The original request is a relatively common thing to want to do, so I was slightly surprised that hoogling for:

(b -> c) -> (a -> f b) -> a -> f c

didn't turn up any relevant results.  This function is a lot like (<=<) but with a pure rather than side-effecting function on the left-hand side.

Thanks,

Neil.