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 "$"