如何将Haskell嵌入批处理文件(hash-bang runhaskell for Windows)?

Mar*_*ica 3 windows haskell cmd batch-file shebang

在安装了GHC的类UNIX系统上,我可以创建一个包含以下内容的文件

#!/usr/bin/env runhaskell
main = putStrLn "Hello, I am a UNIX script file."
Run Code Online (Sandbox Code Playgroud)

使文件可执行,这将执行给定的Haskell代码.

如何在Windows .bat文件中执行等效操作?

最好不要创建额外的文件,不设置环境变量,如果使用UNC路径或包含空格的路径访问批处理文件,它也可以工作,Haskell命名空间不会被污染,如果Haskell代码包含,则会产生合理的行为错误.

Mar*_*ica 10

经过多次反复试验,结果证明是可能的.我设计了以下内容:

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

这种机制的唯一缺点是错误消息包含由(由某个方法调用)创建的临时文件的名称runhaskell.

以下是对其工作原理的完整说明:

  • set /p =-- < nul输出--(和两个不相关的空格)后面没有换行符.这样工作如下:
    • set /p ANSWER=Please enter answer:打印Please enter answer:没有换行符,等待用户输入,并将其放在环境变量中ANSWER.
    • < nul 就像用户没有输入任何东西一样.
    • 作为(未记录的?)特例,可以省略环境变量名,然后不设置环境变量.
  • "%~f0" 是当前批处理文件的名称.
  • 因此set /p =-- < nul & type "%~f0"输出当前批处理文件,但第一行被注释掉(当解释为Haskell代码时).
  • 我把它管道化runhaskell,(无证据?)将其stdin解释为非文字(!)Haskell代码.
    • 就像问题中的UNIX版本一样,这假设runhaskell是当前的PATH.
  • 最后,exit确保Windows批处理文件解释器看不到第一行之后的所有内容,并exit /b确保我们只退出此脚本,而不是任何周围的cmd.exeshell.
  • 领先者@确保echo在运行此脚本时不会编辑所有这些乱码.

(我还没有找到一种方法来为有文化的Haskell代码做同样的事情;但我目前不需要这样做.)