File Paths in Haskell
Here’s the translation of the Go file paths example to Haskell:
Our program demonstrates how to work with file paths in Haskell using the filepath module. This module provides functions to parse and construct file paths in a way that is portable between operating systems.
import System.FilePath
import Data.List (stripPrefix)
main :: IO ()
main = do
-- `combine` should be used to construct paths in a
-- portable way. It takes any number of arguments
-- and constructs a hierarchical path from them.
let p = combine "dir1" $ combine "dir2" "filename"
putStrLn $ "p: " ++ p
-- You should always use `combine` instead of
-- concatenating '/' or '\' manually. In addition
-- to providing portability, `combine` will also
-- normalize paths by removing superfluous separators
-- and directory changes.
putStrLn $ combine "dir1//" "filename"
putStrLn $ combine "dir1/../dir1" "filename"
-- `takeDirectory` and `takeFileName` can be used to split a path to the
-- directory and the file. Alternatively, `splitFileName` will
-- return both in the same call.
putStrLn $ "takeDirectory p: " ++ takeDirectory p
putStrLn $ "takeFileName p: " ++ takeFileName p
-- We can check whether a path is absolute.
putStrLn $ show $ isAbsolute "dir/file"
putStrLn $ show $ isAbsolute "/dir/file"
let filename = "config.json"
-- Some file names have extensions following a dot. We
-- can split the extension out of such names with `takeExtension`.
let ext = takeExtension filename
putStrLn ext
-- To find the file's name with the extension removed,
-- use `dropExtension`.
putStrLn $ dropExtension filename
-- `makeRelative` finds a relative path between a base and a
-- target. It returns the target unchanged if it cannot
-- be made relative to base.
putStrLn $ makeRelative "a/b" "a/b/t/file"
putStrLn $ makeRelative "a/b" "a/c/t/file"To run the program, save it as file-paths.hs and use runhaskell:
$ runhaskell file-paths.hs
p: dir1/dir2/filename
dir1/filename
dir1/filename
takeDirectory p: dir1/dir2
takeFileName p: filename
False
True
.json
config
t/file
../c/t/fileIn this Haskell version:
- We use the
System.FilePathmodule, which provides similar functionality to Go’sfilepathpackage. combineis used instead ofJointo construct file paths.takeDirectoryandtakeFileNameare used instead ofDirandBase.isAbsolutechecks if a path is absolute.takeExtensionextracts the file extension.dropExtensionremoves the extension from a filename.makeRelativefinds a relative path between two paths.
Note that Haskell’s filepath module doesn’t have an exact equivalent to Go’s filepath.Rel. The makeRelative function is similar but behaves slightly differently when the paths can’t be made relative.
Haskell’s approach to file paths is similar to Go’s, providing a portable way to work with paths across different operating systems.