Reading Files in Idris

Here’s the translation of the Go code example for reading files into Idris, formatted in Markdown suitable for Hugo:

Reading and writing files are basic tasks needed for many Idris programs. First we’ll look at some examples of reading files.

import System.File
import Data.String
import Data.Buffer

-- Reading files requires checking most calls for errors.
-- This helper will streamline our error checks below.
check : Either FileError a -> IO a
check (Left err) = die (show err)
check (Right val) = pure val

main : IO ()
main = do
    -- Perhaps the most basic file reading task is
    -- slurping a file's entire contents into memory.
    dat <- check $ readFile "/tmp/dat"
    putStr dat

    -- You'll often want more control over how and what
    -- parts of a file are read. For these tasks, start
    -- by opening a file to obtain a File handle.
    Right f <- openFile "/tmp/dat" Read
        | Left err => die (show err)

    -- Read some bytes from the beginning of the file.
    -- Allow up to 5 to be read but also note how many
    -- actually were read.
    Right b1 <- readBufferFromFile f 5
        | Left err => die (show err)
    n1 <- getBufferSize b1
    str1 <- bufferToString b1
    putStrLn $ show n1 ++ " bytes: " ++ str1

    -- You can also seek to a known location in the file
    -- and read from there.
    Right () <- seek f 6 SeekAbsolute
        | Left err => die (show err)
    Right b2 <- readBufferFromFile f 2
        | Left err => die (show err)
    n2 <- getBufferSize b2
    str2 <- bufferToString b2
    putStrLn $ show n2 ++ " bytes @ 6: " ++ str2

    -- There is no built-in rewind, but
    -- seek 0 SeekAbsolute accomplishes this.
    Right () <- seek f 0 SeekAbsolute
        | Left err => die (show err)

    -- The Idris standard library doesn't provide a buffered
    -- reader like Go's bufio. For efficiency with many small
    -- reads, you might need to implement your own buffering.

    -- Close the file when you're done (usually this would
    -- be scheduled immediately after opening with a
    -- try-finally block or similar construct).
    closeFile f

To run the program:

$ echo "hello" > /tmp/dat
$ echo "idris" >> /tmp/dat
$ idris -o reading-files reading-files.idr
$ ./reading-files
hello
idris
5 bytes: hello
2 bytes @ 6: id

Note that Idris’s file handling is quite different from Go’s. It uses the Either type for error handling, and many operations return IO actions. The Buffer type is used for reading binary data, and we convert it to a string for display.

Idris doesn’t have a direct equivalent to Go’s bufio package or Seek operations, so we’ve simplified those parts. For more complex file operations, you might need to implement additional functionality or use external libraries.

Next, we’ll look at writing files.