----------------------------------------------------------------------------- -- | -- Module : System.IO.Read -- -- Read a from FilePath ----------------------------------------------------------------------------- module System.IO.Read ( readFrom , readIn , readDirectory , listAbsDirectory , listFromIndexedMap , indexedMap , indexed ) where import System.Directory (canonicalizePath, listDirectory) import System.FilePath (()) import System.IO (openFile, IOMode(ReadMode), hSetEncoding, hGetContents, utf8) import Data.List (sort) import Data.Map (Map, fromList, toList) -- ----------------------------------------------------------------------------- -- Reading -- | Read UTF-8 file to String readFileUtf8 :: FilePath -> IO String readFileUtf8 path = do handle <- openFile path ReadMode hSetEncoding handle utf8 hGetContents handle -- | Read from given file path readFrom :: (Read a) => FilePath -> IO a readFrom path = readIO =<< readFileUtf8 =<< canonicalizePath path -- | Read files in given basedir and subpath readIn :: (Read a) => FilePath -> FilePath -> IO [a] readIn basedir subpath = readDirectory (basedir subpath) -- | Read from given directory readDirectory :: (Read a) => FilePath -> IO [a] readDirectory dir = mapM readFrom =<< listAbsDirectory dir -- ----------------------------------------------------------------------------- -- Listing -- | List directories with canonicalized paths listAbsDirectory :: FilePath -> IO [FilePath] listAbsDirectory dir = sort <$> listDirectory dir >>= mapM (canonicalizePath . (dir )) -- | Create list of files for given function and i^ndex. listFromIndexedMap :: Read c => (b1 -> b2 -> IO FilePath) -> Map (a1, a2) (b1, b2) -> IO [((a1, a2), c)] listFromIndexedMap f index = sequence [ uncurry2 ((a1, b1), readIO =<< readFileUtf8 =<< f a2 b2) | ((a1, b1), (a2, b2)) <- toList index ] -- | Uncurry uncurry2 :: Functor f => (a1, f a) -> f (a1, a) uncurry2 = uncurry $ fmap . (,) -- ----------------------------------------------------------------------------- -- Indexing -- | Create a indexed map from a and b indexedMap :: (Ord t1, Ord t, Num t1, Num t, Enum t1, Enum t) => [t2] -> [t3] -> Map (t, t1) (t2, t3) indexedMap a b = pairedMap (indexed a) (indexed b) -- | Create an indexed list indexed :: (Num a, Enum a) => [b] -> [(a, b)] indexed = zip [0..] -- | Create a paired map pairedMap :: (Ord t1, Ord t) => [(t, t2)] -> [(t1, t3)] -> Map (t, t1) (t2, t3) pairedMap a b = fromList $ pairedCartProd a b -- | Create the paired cartesian product pairedCartProd :: [(t, t2)] -> [(t1, t3)] -> [((t, t1), (t2, t3))] pairedCartProd a b = [((a1, b1), (a2, b2)) | (a1, a2) <- a, (b1, b2) <- b]