LINUX.ORG.RU

Не могу создать трубу

 ,


0

1
import System.Process
import System.IO

main = do
	(_,Just hOut,_,_) <- createProcess(proc "ls" []){std_out = CreatePipe}
	f <- hReady hOut
	if f then hGetLine hOut >>= print
	     else putStrLn "Can't read"

Пишет can't read. Если в качестве std_out давать файл, то все пишется, а если CreatePipe, то не работает. Почему?

★★★★★

import System.IO
import System.Process

countLines :: String -> IO ()
countLines = putStr . unlines . zipWith (\n l -> show n ++ ": " ++ l) [1..] . lines

main = do (_, Just hOut, _, _) <- createProcess (proc "ls" ["-l"]) { std_out = CreatePipe }
          hGetContents hOut >>= countLines
          hClose hOut
╓─[nameless@desktop]┅┅(~/samples/haskell)
╙─[%> ./sample 
1: итого 1236
2: drwxrwxr-x. 2 nameless nameless    4096 янв.  20 22:25 match
3: drwxrwxr-x. 8 nameless nameless    4096 нояб.  4 01:04 rwh
4: -rwxrwxr-x. 1 nameless nameless 1228332 апр.   9 01:00 sample
5: -rw-rw-r--. 1 nameless nameless     957 апр.   9 01:00 sample.hi
6: -rw-rw-r--. 1 nameless nameless     316 апр.   9 01:00 sample.hs
7: -rw-rw-r--. 1 nameless nameless      38 апр.   9 00:47 sample.hs~
8: -rw-rw-r--. 1 nameless nameless   12792 апр.   9 01:00 sample.o
theNamelessOne ★★★★★
()

Почему?

Ввода не существует до первого обращения к нему (ленивость), поэтому hReady и выдавал такой результат:

import System.IO
import System.Process

check :: Handle -> IO ()
check hdl = do ready <- hReady hdl
               putStrLn $ "[handle: " ++ if ready then "ready]" else "not ready]"

main = do (_, Just hOut, _, _) <- createProcess (proc "ls" ["-l"]) { std_out = CreatePipe }
          check hOut          
          hGetLine hOut >>= putStrLn . ("First line:\n" ++)
          check hOut
          hGetContents hOut >>= putStr . ("Rest lines:\n" ++)
          hClose hOut
theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Ленивость не при чём. ls просто не успевает ничего записать в трубу. Вставь threadDelay и убедись

anonymous
()
Ответ на: комментарий от theNamelessOne

Тогда почему, когда я связываю вот так оно подвисает: reciver.hs:

main = (readLn :: IO Int) >>= (\n -> hPrint stderr $ product [1.. n])
sender.hs:
import System.Process
import System.IO
import Data.Maybe

printNGetValue :: Handle -> Handle -> IO String
printNGetValue hi ho = do
	hPrint hi 5
	system "sleep 1"
	hGetLine ho

main = do (hIn' , hOut', _, _) <- createProcess (proc "./reciver" []) {std_in = CreatePipe, std_out = CreatePipe }
          case hIn' >>= (\x -> hOut' >>= return.(printNGetValue x)) of
          {
          	(Just s) -> s >>= putStrLn >> hClose (fromJust hIn') >> hClose (fromJust hOut');
          	Nothing  -> print "error"
          }
Оно должно вывести 120, а оно повисает.

Aswed ★★★★★
() автор топика
Ответ на: комментарий от Aswed

Я неправильный код там написал, там на самом деле:

main = (readLn :: IO Int) >>= \n -> print (product [1.. n])
Но оно все равно подвисает

Aswed ★★★★★
() автор топика
Ответ на: комментарий от unC0Rr

«print» всегда добавляет перевод строки, да и программа завершается после вывода, так, reciver напечатает текст обязательно.

Aswed ★★★★★
() автор топика
Ответ на: комментарий от unC0Rr

В строчке [code=haskell] case hIn' >>= (\x -> hOut' >>= return.(printNGetValue x)) of [/code] «>>=» - передача в монаде Nothing, здесь return == Just, без него не прокатит.

Aswed ★★★★★
() автор топика
Ответ на: комментарий от Aswed

*в монаде Maybe

 case hIn' >>= (\x -> hOut' >>= return.(printNGetValue x)) of 

Aswed ★★★★★
() автор топика
Ответ на: комментарий от unC0Rr

Да, да, да, спасибо, я отключил буферизацию и все заработало. Вот она вооот, программа моей мечты))

Aswed ★★★★★
() автор топика
Ответ на: комментарий от Aswed

Да, точно... Что-то у меня парсер хромает. Что интересно, я эту задачу успешно решил в своём проекте, и не вижу, в чём у тебя проблема. Можешь покопаться тут: http://code.google.com/p/hedgewars/source/browse/#hg/gameServer/OfficialServer файлы DBInteraction.hs для опрашивателя и extdbinterface.hs для ответчика.

unC0Rr ★★★★★
()
Ответ на: комментарий от Aswed

Можно еще сбрасывать буфер hIn:

import System.IO
import System.Process

main = do (Just hIn, Just hOut, _, _) <- createProcess (proc "./reciever" [])
                                        { std_out = CreatePipe, std_in = CreatePipe }
          hPrint hIn 5
          hFlush hIn
          hGetContents hOut >>= putStr
          hClose hIn
          hClose hOut
theNamelessOne ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.