[Haskell-cafe] Using external programs with Haskell in windows.

Christian Lean christian.lean2 at bigpond.com
Sun Mar 18 21:54:14 EDT 2007


Donald Bruce Stewart wrote:
> christian.lean2:
>   
>> Donald Bruce Stewart wrote:
>>     
>>> christian.lean2:
>>>  
>>>       
>>>> I'm looking for a way to run an external program and get the results in 
>>>> haskell. Something similar to HSH but that will work in windows. I don't 
>>>> need anything too complex, just to provide the command to be run as a 
>>>> string and get the result as a string. Is this possible?
>>>> One of the HSH examples is all I need:
>>>>
>>>> runS $ "echo /etc/pass*"
>>>> -> "/etc/passwd /etc/passwd-"
>>>>    
>>>>         
>>> System.Process is your friend. E.g.
>>>
>>>
>>>    import System.Process
>>>    import Control.Exception
>>>    import System.IO
>>>    import System.Exit
>>>
>>>    --
>>>    -- Run a normal shell command
>>>    --
>>>    run :: String -> IO String
>>>    run s = handle (fail . show) $ do
>>>        (ih,oh,eh,pid) <- runInteractiveCommand s
>>>        so <- hGetContents oh
>>>        se <- hGetContents eh
>>>        hClose ih
>>>        ex <- waitForProcess pid
>>>        case ex of
>>>            ExitFailure e      -> fail $ "Failed with status: " ++ show e
>>>            _  | not (null se) -> fail se
>>>               | otherwise     -> return so
>>>
>>>
>>> *Process> run $ "echo *.hs"
>>> "Main.hs Process.hs Shell.hs\n"
>>>
>>> -- Don
>>>
>>>  
>>>       
>> Thank you for the speedy reply, I am trying to follow what the code is 
>> trying to do, is this correct?
>> runInteractiveCommand:
>> This gives you handles for stdin, stdout, stderr,  and the process 
>> running the command.
>> You can then use functions like hPutStrLn with stdin or hGetContents 
>> with stdout and stderr.
>>     
>
> Right.
>
>   
>> waitForProcess just stops that part of the code until the command has 
>> finished.
>>     
>
> Yep.
>
>   
>> Is nClose ih necessary, none of the others are closed so I'm guessing 
>> this is needed else waitForProcess will never finish.
>>     
>
> They should be closed too I suspect.
>
>   
>> Does this have to do with run_Interactive_Command, could I keep passing 
>> commands and getting responses until I close the input.
>>     
>
> Not with that code, but you could modify it to do so.
>   
>   
>> The two parts i'm having trouble following are:
>>
>> run s = handle (fail . show) $ do
>>     
>
> That's an exception handler that just shows the exception in the current
> monad.
>
>   
>> handle has type:
>>
>> handle :: (Exception -> IO a) -> IO a -> IO a
>>
>> Is (fail . show) composing a fuction of type
>>
>> Exception -> IO a)
>>
>> and what part is the middle IO a, is that the whole block that 
>> follows(ie the do block)
>>     
>
> Yes.
>   
>   
>> Also
>>
>> case ex of
>>    ExitFailure e      -> fail $ "Failed with status: " ++ show e
>>    _  | not (null se) -> fail se
>>       | otherwise     -> return so
>>
>> I dont quite get this part. I understand that you are checking for 
>> errors(not (null se)) otherwise returning everything gotten from stdout 
>> but I don't get
>> the ExitFailure line.
>>     
>
> That checks the exit status of the program, as reported by
> waitForProcess, the other cases check for stderr.
>
>   
>> I have one final question, how should you go about finding functions 
>> like runInteractiveCommand?
>>     
>
> hoogle!
>
>     http://www.haskell.org/hoogle/?q=Command
>
>   
>> If I had that to begin with I might have had a chance to try some of the 
>> above on my own but I find that it is difficult to know where to start.
>>     
>
> Hoogle, and the library docs, are helpful here.
>
> -- Don
>
>   
Just a quick thankyou, the response has been very helpful.


More information about the Haskell-Cafe mailing list