Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to embed Haskell in a batch file (hash-bang runhaskell for Windows)?

On a UNIX-like system with GHC installed, I can create an file with the following contents

#!/usr/bin/env runhaskell
main = putStrLn "Hello, I am a UNIX script file."

Make the file executable, and this executes the given Haskell code.

How do I do the equivalent in a Windows .bat file?

Preferably, no extra files are created, no environment variables are set, it also works if the batch file is accessed using a UNC path or a path containing spaces, the Haskell namespace is not polluted, and a reasonable behavior results if the Haskell code contains errors.

like image 426
MarnixKlooster ReinstateMonica Avatar asked Dec 09 '22 18:12

MarnixKlooster ReinstateMonica


2 Answers

After much trial and error, this turns out to be possible. I have designed the following:

@(set /p =-- < nul & type "%~f0") | runhaskell & exit /b
main = putStrLn "Hello, I am a Windows batch file."

The only disadvantage of this mechanism is that error messages contain the name of a temp file created by (something called by) runhaskell.

Here is a full explanation of how this works:

  • set /p =-- < nul outputs -- (and two irrelevant spaces) not followed by a newline. This works like this:
    • set /p ANSWER=Please enter answer: prints Please enter answer: without a newline, waits for user input, and puts that in environment variable ANSWER.
    • < nul acts as if the user did not enter anything.
    • As an (undocumented?) special case, the environment variable name can be left out, and then no environment variable is set.
  • "%~f0" is the name of the current batch file.
  • Therefore set /p =-- < nul & type "%~f0" outputs the current batch file, but with the first line commented out (when interpreted as Haskell code).
  • We pipe this into runhaskell, which (undocumentedly?) interprets its stdin as non-literal (!) Haskell code.
    • Like in the UNIX version in the question, this assumes that runhaskell is on the current PATH.
  • Finally, exit makes sure that everything after the first line is not seen by the Windows batch file interpreter, and exit /b makes sure that we only exit this script, not any surrounding cmd.exe shell.
  • And the leading @ makes sure that all this gibberish is not echoed when running this script.

(I have not found a way to do the same for literate Haskell code; but I don't have a need for that currently.)

like image 189
MarnixKlooster ReinstateMonica Avatar answered Dec 11 '22 10:12

MarnixKlooster ReinstateMonica


Simply create under your PATH

C:\my-tools-path>copy con --.bat
runhaskell %1
^Z

To create your auto-executable haskell program write some like

-- "%~f0"
main = putStrLn "Merry Christmas!"

No errors, no temp files, ...

;)

(You can add your program args changing

runhaskell %1 %2 ...

and

-- "%~f0" %1 %2 ...

)

like image 25
josejuan Avatar answered Dec 11 '22 12:12

josejuan