Execing Processes in Idris

Here’s the translation of the Go code to Idris, formatted in Markdown suitable for Hugo:

Our example demonstrates how to replace the current process with another one using Idris. This is similar to the classic exec function in Unix-like operating systems.

import System
import System.File

main : IO ()
main = do
    -- For our example, we'll exec 'ls'. We need to provide the full path to the binary.
    let binary = "/bin/ls"
    
    -- We'll give 'ls' a few common arguments. Note that the first argument should
    -- be the program name.
    let args = ["ls", "-a", "-l", "-h"]
    
    -- We also need to provide the environment variables.
    env <- getEnvironment
    
    -- Here's the actual exec call. If this call is successful, the execution of our
    -- process will end here and be replaced by the '/bin/ls -a -l -h' process.
    -- If there is an error, it will be returned.
    result <- execve binary args env
    case result of
        Left err -> putStrLn $ "Exec failed: " ++ show err
        Right _ -> pure () -- This line will never be reached if exec is successful

When we run our program, it is replaced by ls:

$ idris -o exec_process exec_process.idr
$ ./exec_process
total 16
drwxr-xr-x  4 user 136B Oct 3 16:29 .
drwxr-xr-x 91 user 3.0K Oct 3 12:50 ..
-rw-r--r--  1 user 1.3K Oct 3 16:28 exec_process.idr

In this Idris version:

  1. We use the System and System.File modules which provide system-level operations.

  2. Instead of exec.LookPath, we directly use the full path to the ls binary. Idris doesn’t have a built-in function to look up executables in the PATH.

  3. We use getEnvironment to get the current environment variables.

  4. The execve function is used to replace the current process. It returns an Either type, allowing us to handle potential errors.

  5. We use pattern matching to handle the result of execve. If it’s successful, the current process is replaced and the error case will never be reached.

Note that Idris, being a purely functional language, handles effects differently from imperative languages. The IO monad is used to sequence effects, and the do notation is used for more readable imperative-style code within IO.