[Haskell-cafe] Trouble with simple embedding of shell in haskell
Bulat Ziganshin
bulat.ziganshin at gmail.com
Thu Sep 21 04:50:37 EDT 2006
Hello George,
Thursday, September 21, 2006, 7:44:22 AM, you wrote:
> sh :: String -> String -> IO String
> sh cmd = \input ->
> do (stdin, stdout, _, pid) <- runInteractiveCommand cmd
> forkIO $ hPutStr stdin input >> hClose stdin
> -- get exit status to prevent zombie accumulation
> forkIO $ waitForProcess pid >> return ()
> hGetContents stdout
1. when 'main' finishes, all the threads created by forkIO, silently
dies. typically you need to wait until they are finished. ghc
libraries don't provide any provision for it, they are too low-level.
you can consider writing your own simple wrapper using MVar:
myFork action = do
v <- newEmptyMVar
forIO $ action >>= putMVar v
return v
finishHim v = takeMVar v
which also returns value returned by action. usage:
subProcess <- myFork $ do-something-here
...
finishHim subProcess
or you can use some simple libraries which use more developed
solutions of this problem:
http://freearc.narod.ru/Process.tar.gz (my own)
http://www-i2.informatik.rwth-aachen.de/~stolz/Haskell/CA.hs
2. afaiu, you don't want to wait for process finishing before calling
getContents? in this case you need to collect all 'pids' returned by
myFork function in some list and finish them all before main returns.
or, better, develop more complex interface that will allow to kill
processes whose output is no more required, in order to help
'head'-like processes
also look at
http://www.haskell.org/~petersen/haskell/popenhs/popenhs-1.00.0.tar.gz
http://www.volker-wysk.de/hsshellscript/dist/hsshellscript-2.5.0.tar.gz
and file i attached
also, look at "Tackling the awkward squad: monadic input/output,
concurrency, exceptions, and foreign-language calls in Haskell"
http://research.microsoft.com/Users/simonpj/papers/marktoberdorf/marktoberdorf.ps.gz
paper, which is a definitive source of information about GHC
concurrency implementation
--
Best regards,
Bulat mailto:Bulat.Ziganshin at gmail.com
-------------- next part --------------
Following the "release early, release often" motto, I am happy to
announce version 0.1.0 of HSH, the Haskell shell.
You may obtain it with:
darcs get --tag 0.1.0 http://darcs.complete.org/hsh
Things are still very rough in many ways, but this version already lets
you:
* Run commands
* Pipe things between commands
* Pipe command input/output into and out of pure Haskell functions
* Pure Haskell functions are as much a first-class citizen as
is grep or cat
Here is an example session:
$ ghci -fglasgow-exts HSH
*HSH> run $ ("ls", ["."])
COPYING HSH HSH.hs TODO announcements testsrc
COPYRIGHT HSH.cabal Makefile _darcs test.hs
*HSH> run $ ("ls", ["-l"]) -|- ("wc", ["-l"])
12
*HSH> :m +Text.Printf
*HSH Text.Printf> let countLines = (zipWith (\i line -> printf "%-5d %s" i line) [(1::Int)..])::([String] -> [String])
*HSH Text.Printf> run $ ("ls", ["-l"]) -|- countLines -|- ("grep", ["hs$"])
6 -rw-r--r-- 1 jgoerzen jgoerzen 1285 Jun 6 09:43 HSH.hs
11 -rw-r--r-- 1 jgoerzen jgoerzen 565 Jun 6 09:43 test.hs
*HSH Text.Printf> :m +Data.List
*HSH Text.Printf Data.List> run $ ("ls", ["-l"]) -|- countLines -|- filter (isSuffixOf "hs")
6 -rw-r--r-- 1 jgoerzen jgoerzen 1285 Jun 6 09:43 HSH.hs
11 -rw-r--r-- 1 jgoerzen jgoerzen 565 Jun 6 09:43 test.hs
*HSH Text.Printf Data.List> run $ ("ls", ["-l"]) -|- countLines -|- filter (isSuffixOf "hs") -|- ("tr", ["a-z", "A-Z"])
6 -RW-R--R-- 1 JGOERZEN JGOERZEN 1285 JUN 6 09:43 HSH.HS
11 -RW-R--R-- 1 JGOERZEN JGOERZEN 565 JUN 6 09:43 TEST.HS
*HSH Text.Printf Data.List> let generator = \(_::String) -> unlines . map show $ [1..20]
*HSH Text.Printf Data.List> generator ""
"1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n"
*HSH Text.Printf Data.List> run $ generator -|- ("grep", ["1"])
1
10
11
12
13
14
15
16
17
18
19
Future versions will likely simplify syntax to make it easier to write scripts
and introduce a sh to hsh converter. I also plan to add pure Haskell
tools for some common shell-ish things that one could do in Haskell.
-- John
More information about the Haskell-Cafe
mailing list