suztomoの日記

To be a good software engineer

Iteratee with IO

Around p.27 of Monad.Reader#16.

type EnumeratorM el m a = IterV el a -> m (IterV el a)

enumHandle :: Handle -> EnumeratorM Char IO a
--                      IterV Char a -> m (IterV Char a)
enumHandle h iter = loop iter where
    loop :: IterV Char a -> IO (IterV Char a)
    loop i@(Done _ _) = return i
    loop i@(Cont k) = do
      isEOF <- hIsEOF h
      if isEOF
      then return i
      else do
        e <- hGetChar h
        loop . k . El $ e
--             k :: (StreamG Char -> IterV Char a)


enumFile :: FilePath -> EnumeratorM Char IO a
--                      IterV Char a -> m (IterV Char a)
enumFile fp i = bracket
                   (openFile fp ReadMode)
                   (hClose)
                   (flip enumHandle i)
                   
lengthOfTwoFiles :: FilePath -> FilePath -> IO (Maybe Int)
lengthOfTwoFiles fp1 fp2 =
    fmap run $ ((enumFile fp1) >=> (enumFile fp2)) length
-- enumFile fp1 :: IterV Char a -> IO (IterV Char a) -> x -> m x
-- enumFile fp2 :: IterV Char a -> IO (IterV Char a) -> x -> m x
-- length :: IterV el Int                           -> x
-- (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c

The last fmap works over "IO (IterV Char Int)", the right side of "$"