2016-10-01 6 views
4

Есть ли какой-нибудь модуль в стандартной библиотеке Idris (или сторонней библиотеке), который позволяет обходить другую программу? Я думаю о модулях, таких как subprocess Python и Haskell's System.Process.Как я могу назвать подпроцесс в Идрисе?

В идеале, я хотел бы взаимодействовать программно с процессом (записывая его в stdin, считывая его из stdout и т. Д.).

+0

Существует функция 'system: String -> IO Int', которая принимает команду оболочки и возвращает ее код выхода. Вам нужно будет «импортировать систему», чтобы использовать ее. –

+0

@AntonTrunov Звучит как достойный ответ щедрый ответ –

+0

@BenjaminHodgson Спасибо. Развернул его в ответ. –

ответ

2

Функция system : String -> IO Int, которая принимает команду оболочки, запускает ее и возвращает код выхода. Вам нужно 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 

В моей системе вышеуказанный код приводит следующий вывод:

HelloWorld! 
Exit code: 0 
HelloWorld! 
Exit code: 256 

Я бы ожидать, что она вернется 1 вместо 256 во втором дело. По крайней мере, это то, что показывают echo $?.


Другим вариантом можно сделать исходя из Effects библиотеки, которая описана в this учебнике:

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 

Здесь нужно объяснить Идрис, что он нуждается в Effects пакете:

idris -p effects <filename.idr> 

Я не знаю ни одного Идриса который позволяет вам легко работать с stdin/stdout подпроцесса. В качестве обходного пути мы можем использовать объекты труб 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 

При запуске программы, вы должны увидеть

Here is what we got: 
Captured output 
+0

Есть ли вариант 'system', который позволяет передавать объекты в потоки stdin/out подпроцесса? –

+0

Я обновил ответ на примере того, как записывать stdout. 'system' является просто оболочкой для функции C' system() ', поэтому я думаю, что с ней невозможно взаимодействовать. –

+1

Отличный ответ. Идрису нужно больше «получить материал», как это. Баунти с удовольствием дается! –