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

Donald Bruce Stewart dons at cse.unsw.edu.au
Sun Mar 18 20:07:22 EDT 2007


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


More information about the Haskell-Cafe mailing list