出力の一時停止と再開
Posted feedbacks - Haskell
Haskellでも多言語同様にコンソール入力がエンターを押すまで読めない病にかかっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | module Main where
import System
import System.IO
import System.IO.Error
import Control.Monad
weaveIO :: (IO Bool) -> IO a -> (a -> IO a) -> IO a
weaveIO w m f = do
a <- m
b <- w
if b then f a
else return a
getChar' :: IO Char
getChar' = getLine >>= return.head.(++" ")
nonBlockingGetCh :: IO (Maybe Char)
nonBlockingGetCh = do
f <- hReady stdin
if (not f) then return Nothing
else do
getChar' >>= return.Just
respondToKey :: IO Bool
respondToKey = nonBlockingGetCh >>= evalCh
where
evalCh Nothing = return True
evalCh (Just 'q') = print "+++ quitting +++" >> return False
evalCh (Just 'p') = waitForP ' '
evalCh _ = return True
waitForP 'p' = return True
waitForP 'q' = print "+++ quitting +++" >> return False
waitForP _ = print "+++ paused, hit 'p' again +++" >> getChar' >>= waitForP
showLineWeave :: Handle -> IO ()
showLineWeave h = weaveIO (respondToKey) (hGetLine h >>= putStrLn) (\_ -> showLineWeave h)
main = do
args <- getArgs
withFile (head args) ReadMode $ \h ->
catch (showLineWeave h) (\e -> if (isEOFError e) then return () else ioError e)
|
こちらが題意に沿ったものになります
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | module Main where
import System
import System.IO
import System.IO.Error
import Control.Monad
import Control.Concurrent
weaveIO :: (IO Bool) -> IO a -> (a -> IO a) -> IO a
weaveIO w m f = do
a <- m
b <- w
if b then f a
else return a
getChar' :: IO Char
getChar' = getLine >>= return.head.(++" ")
nonBlockingGetCh :: IO (Maybe Char)
nonBlockingGetCh = do
f <- hReady stdin
if (not f) then return Nothing
else do
getChar' >>= return.Just
respondToKey :: IO Bool
respondToKey = nonBlockingGetCh >>= evalCh
where
evalCh Nothing = return True
evalCh (Just 'q') = print "+++ quitting +++" >> return False
evalCh (Just 'p') = waitForP ' '
evalCh _ = return True
waitForP 'p' = return True
waitForP 'q' = print "+++ quitting +++" >> return False
waitForP _ = print "+++ paused, hit 'p' again +++" >> getChar' >>= waitForP
showLineWeave :: IO ()
showLineWeave = weaveIO (respondToKey) (putStr "a" >> hFlush stdout >> threadDelay 1000000) (\_ -> showLineWeave)
main = showLineWeave
|
ghc-6.8.2 の System.Timeout を使ってみた 標準入出力をNoBufferingモードで使う ユーザキー入力はechoしないようにする Windowsで動くかどうかは未確認
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | module Main where
import System.IO
import System.Posix
import System.Timeout
main :: IO ()
main = do { hSetBuffering stdin NoBuffering
; hSetBuffering stdout NoBuffering
; at <- getTerminalAttributes stdInput
; setTerminalAttributes stdInput (withoutMode at EnableEcho) Immediately
; loop False
}
loop :: Bool -> IO ()
loop False = do {
; mc <- timeout (10^6) (hGetChar stdin)
; case mc of
Nothing -> hPutChar stdout 'a' >> loop False
Just 'p' -> loop True
Just 'q' -> return ()
Just _ -> loop False
}
loop True = do {
; c <- hGetChar stdin
; case c of
'p' -> loop False
'q' -> return ()
_ -> loop True
}
|




nobsun
#6346()
Rating3/3=1.00
起動すると、標準出力に1秒毎に'a'の1文字を出力し続けるプログラムで、 以下の条件を満たすものを「どう書く?」
[ reply ]