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.
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."%~f0"
is the name of the current batch file.set /p =-- < nul & type "%~f0"
outputs the current batch file, but with the first line commented out (when interpreted as Haskell code).runhaskell
, which (undocumentedly?) interprets its stdin as non-literal (!) Haskell code.
runhaskell
is on the current PATH
.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.@
makes sure that all this gibberish is not echo
ed 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.)
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 ...
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With