Haskell:立即从控制台读取input字符,而不是在换行符之后

我试过这个:

main = do hSetBuffering stdin NoBuffering c <- getChar 

但是等到input被按下,这不是我想要的。 我想在用户按下后立即读取字符。

我在Windows 7上使用ghc v6.12.1。

编辑:我的解决方法是从GHC移动到WinHugs,正确支持这一点。

Solutions Collecting From Web of "Haskell:立即从控制台读取input字符,而不是在换行符之后"

可能是一个错误:

http://hackage.haskell.org/trac/ghc/ticket/2189

以下程序重复输入的字符,直到按下退出键。

 import IO import Monad import Char main :: IO () main = do hSetBuffering stdin NoBuffering inputLoop inputLoop :: IO () inputLoop = do i <- getContents mapM_ putChar $ takeWhile ((/= 27) . ord) i 

由于hSetBuffering stdin NoBuffering行,不需要在击键之间按下Enter键。 此程序在WinHugs(sep 2006版本)中正常工作。 但是,直到按下回车键,GHC 6.8.2才会重复字符。 所有GHC可执行文件(ghci,ghc,runghc,runhaskell)都使用Windows XP Professional上的cmd.exe和command.com来重现问题…

是的,这是一个错误。 这是一个解决方法,以保存人们点击和滚动:

 {-# LANGUAGE ForeignFunctionInterface #-} import Data.Char import Foreign.C.Types getHiddenChar = fmap (chr.fromEnum) c_getch foreign import ccall unsafe "conio.h getch" c_getch :: IO CInt 

所以你可以用getChar调用来代替getChar的调用。

请注意,这是一个解决方法,仅适用于Windows上的ghc / ghci。 例如,winhugs没有bug,这个代码在winhugs中不起作用。

嗯..其实我看不到这个功能是一个错误。 当你阅读stdin ,这意味着你想用一个“文件”,当你打开缓冲你说没有需要读取缓冲区。 但这并不意味着模拟“文件”的应用程序不应该使用写入缓冲区。 对于Linux,如果你的终端处于“icanon”模式,它将不会发送任何输入,直到发生一些特殊事件(如Enter按或Ctrl + D)。 Windows中的控制台可能有一些类似的模式。

Haskeline包为我工作。

如果你需要单个字符,那么稍微改变一下这个例子。

  1. getInputLine变成getInputChar
  2. "quit"变成'q'
  3. ++ input变成++ [input]
 main = runInputT defaultSettings loop where loop :: InputT IO () loop = do minput <- getInputChar "% " case minput of Nothing -> return () Just 'q' -> return () Just input -> do outputStrLn $ "Input was: " ++ [input] loop