如何在Idris中调用子流程?

Lan*_*ton 5 functional-programming process idris

Idris标准库(或第三方库)中是否有一些模块可以允许用户使用Shell扩展到另一个程序?我在考虑像Python subprocess和Haskell 这样的模块System.Process

理想情况下,我想以编程方式与该流程进行交互(写入其stdin,从其stdout读取等)。

Ant*_*nov 3

有一个system : String -> IO Int函数接受 shell 命令,运行它,并返回其退出代码。你需要import System使用它:

import System

main : IO ()
main = do
  exitCode <- system "echo HelloWorld!"
  putStrLn $ "Exit code: " ++ show exitCode

  exitCode <- system "echo HelloWorld!; false"
  putStrLn $ "Exit code: " ++ show exitCode
Run Code Online (Sandbox Code Playgroud)

在我的系统上,上述代码会产生以下输出:

HelloWorld!
Exit code: 0
HelloWorld!
Exit code: 256
Run Code Online (Sandbox Code Playgroud)

我希望它会返回,1而不是256第二种情况。至少它是这样echo $?显示的。


可以基于该Effects库制作另一个版本,教程中对此进行了描述:

import Effects
import Effect.System
import Effect.StdIO

execAndPrint : (cmd : String) -> Eff () [STDIO, SYSTEM]
execAndPrint cmd = do
  exitCode <- system cmd
  putStrLn $ "Exit code: " ++ show exitCode

script : Eff () [STDIO, SYSTEM]
script = do
  execAndPrint "echo HelloWorld!"
  execAndPrint "sh -c \"echo HelloWorld!; exit 1\""

main : IO ()
main = run script
Run Code Online (Sandbox Code Playgroud)

这里我们需要向 Idris 解释一下它需要这个Effects包:

idris -p effects <filename.idr>  
Run Code Online (Sandbox Code Playgroud)

我不知道有任何 Idris 库可以让您轻松使用子进程的标准输入/标准输出。作为一种解决方法,我们可以使用 C 的管道设施,利用其popen/pclose函数,这些函数已经绑定在 Idris 标准库中。让我展示一下我们如何从子进程的标准输出中读取数据(请记住,这是一个带有基本错误处理的简单片段):

import System

-- read the contents of a file
readFileH : (fileHandle : File) -> IO String
readFileH h = loop ""
  where
    loop acc = do
      if !(fEOF h) then pure acc
      else do
        Right l <- fGetLine h | Left err => pure acc
        loop (acc ++ l)

execAndReadOutput : (cmd : String) -> IO String
execAndReadOutput cmd = do
  Right fh <- popen cmd Read | Left err => pure ""
  contents <- readFileH fh 
  pclose fh
  pure contents

main : IO ()
main = do
  out <- (execAndReadOutput "echo \"Captured output\"")
  putStrLn "Here is what we got:"
  putStr out
Run Code Online (Sandbox Code Playgroud)

当你运行程序时,你应该看到

Here is what we got:
Captured output
Run Code Online (Sandbox Code Playgroud)