Я попробовал это:
main = do
hSetBuffering stdin NoBuffering
c <- getChar
но это ожидает, пока Enter не нажат, который не является тем, что я хочу. Я хочу считать символ сразу после того, как пользователь нажмет его.
Я использую ghc v6.12.1 в Windows 7.
Править: обходное решение для меня перемещалось от GHC до WinHugs, который поддерживает это правильно.
Возможно, это ошибка:
http://hackage.haskell.org/trac/ghc/ticket/2189
Следующая программа повторяет введенные символы до тех пор, пока не будет нажата клавиша escape.
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 не должно быть необходимости нажимать клавишу ввода между нажатиями клавиш. Эта программа корректно работает в WinHugs (версия sep 2006). Однако в GHC 6.8.2 символы не повторяются до тех пор, пока не будет нажата клавиша Enter. Проблема была воспроизведена со всеми исполняемыми файлами GHC (ghci, ghc, runghc, runhaskell), используя cmd.exe и command.com на Windows XP Professional...
Хм .. На самом деле я не считаю, что эта функция является ошибкой. Когда вы читаете stdin
, это означает, что вы хотите работать с «файлом», а когда вы включаете буферизацию, вы говорите, что нет необходимости в буфере чтения. Но это не означает, что приложение, которое имитирует этот «файл», не должно использовать буфер записи. Для linux, если ваш терминал находится в режиме «icanon», он не отправляет никаких входных данных, пока не произойдет какое-то особое событие (например, нажатие Enter или Ctrl + D). Наверное, в консоли в Windows есть какие-то похожие режимы.