ghc, readline, and buffering woes

Here’s a very simple Haskell program:

import System.Console.Readline

main :: IO ()
main = do
  putStr "Key: "
  k <-  readKey
  putStrLn [k]

Looks pretty innocent, right? And it runs just fine with runhaskell. But as soon as you try to compile it with ghc and run it, Segmentation Faults occur. This was a bug that recently bit me with my hlean program.

What is the difference between the two? runhaskell invokes ghci, which makes additional readline initializations before handing it off to your main. The documentation is non-existent, so here is what you need to do in case you come across the same problem:

import System.Console.Readline

main :: IO ()
main = do
  initialize     -- System.Console.Readline.initialize :: IO ()
  putStr "Key: "
  k <-  readKey
  putStrLn [k]

Again, you test it using runhaskell and everything works fine. Except when you build and run it, the prompt just sits there - no matter how many times you hit that key - until you hit the carriage return (for the younger generation, that’s [Enter]). Turns out that initializing Readline is not enough, ghc and ghci have different buffering modes. After even more struggling which you now don’t have to suffer through, here’s the final solution:

import System.Console.Readline
import System.IO

main :: IO ()
main = do
  initialize     -- System.Console.Readline.initialize :: IO ()
  hSetBuffering stdin NoBuffering   -- System.IO
  hSetBuffering stdout NoBuffering  -- System.IO
  putStr "Key: "
  k <-  readKey
  putStrLn [k]

Hope I saved some poor googler some time and stress - I know I would have appreciated finding a post like this earlier. Kudos to pejo and dcoutts on #haskell irc for helping me sort this out.