Directories in Haskell

Here’s the translation of the Go code to Haskell, along with explanations in Markdown format suitable for Hugo:

Our program demonstrates working with directories in Haskell. Here’s the full source code:

import System.Directory
import System.FilePath
import Control.Exception (catch, SomeException)
import Control.Monad (forM_)

main :: IO ()
main = do
    -- Create a new sub-directory in the current working directory.
    createDirectory "subdir"

    -- When creating temporary directories, it's good practice to ensure their removal.
    -- We'll use 'finally' to ensure cleanup happens even if an exception occurs.
    (`finally` removeDirectoryRecursive "subdir") $ do

        -- Helper function to create a new empty file.
        let createEmptyFile name = writeFile name ""

        createEmptyFile "subdir/file1"

        -- We can create a hierarchy of directories, including parents.
        -- This is similar to the command-line `mkdir -p`.
        createDirectoryIfMissing True "subdir/parent/child"

        createEmptyFile "subdir/parent/file2"
        createEmptyFile "subdir/parent/file3"
        createEmptyFile "subdir/parent/child/file4"

        -- listDirectory lists directory contents.
        entries <- listDirectory "subdir/parent"
        putStrLn "Listing subdir/parent"
        forM_ entries $ \entry -> do
            isDir <- doesDirectoryExist $ "subdir/parent" </> entry
            putStrLn $ "  " ++ entry ++ " " ++ show isDir

        -- setCurrentDirectory lets us change the current working directory.
        setCurrentDirectory "subdir/parent/child"

        -- Now we'll see the contents of `subdir/parent/child` when listing the current directory.
        entries <- listDirectory "."
        putStrLn "Listing subdir/parent/child"
        forM_ entries $ \entry -> do
            isDir <- doesDirectoryExist entry
            putStrLn $ "  " ++ entry ++ " " ++ show isDir

        -- Change back to where we started.
        setCurrentDirectory "../../.."

        -- We can also visit a directory recursively, including all its sub-directories.
        putStrLn "Visiting subdir"
        walkDir "subdir"

-- walkDir recursively visits directories and files.
walkDir :: FilePath -> IO ()
walkDir dir = do
    entries <- listDirectory dir
    forM_ entries $ \entry -> do
        let path = dir </> entry
        isDir <- doesDirectoryExist path
        putStrLn $ "  " ++ path ++ " " ++ show isDir
        when isDir $ walkDir path

To run the program, save it as directories.hs and use runhaskell:

$ runhaskell directories.hs
Listing subdir/parent
  child True
  file2 False
  file3 False
Listing subdir/parent/child
  file4 False
Visiting subdir
  subdir/file1 False
  subdir/parent True
  subdir/parent/child True
  subdir/parent/child/file4 False
  subdir/parent/file2 False
  subdir/parent/file3 False

This Haskell program demonstrates various operations on directories:

  1. Creating directories and files
  2. Listing directory contents
  3. Changing the current working directory
  4. Walking a directory tree recursively

The program uses functions from the System.Directory and System.FilePath modules to perform these operations. It also demonstrates how to handle exceptions and ensure cleanup using finally.

Note that Haskell’s approach to file and directory operations is more functional and relies on IO actions, which is different from Go’s more imperative style. However, the core concepts remain similar.