[Haskell-cafe] Loop with the StateT monad

Ben Franksen ben.franksen at online.de
Sun Mar 19 10:33:41 UTC 2017


Am 19.03.2017 um 01:27 schrieb Brandon Allbery:
> On Sat, Mar 18, 2017 at 7:57 PM, Ben Franksen <ben.franksen at online.de>
> wrote:
> 
>> As long as you leave control over these things to the terminal, yes. But
>> what if your program wants to control that itself? E.g. react to
>> keystrokes, rather than edited lines, as the OP seemed to want?
>>
> 
> https://downloads.haskell.org/~ghc/8.0.2/docs/html/libraries/unix-2.7.2.1/System-Posix-Terminal.html

Can System.Posix.Terminal be used on Windows?

> Admittedly some wrappers would be nice... but with care, lest you reproduce
> the same issues stack is having.

Right. With hindsight it seems obvious how to do this right: save the
initial terminal settings and restore them when the program exits.

Let's see if haskeline does the right thing. The following seems to work:

  import System.Console.Haskeline
  getKey = runInputT defaultSettings (getInputChar "")
  main = getKey >>= print

Now we want to see if this leaves the terminal in the same state as it
was before. Unfortunately the obvious thing doesn't work:

  import System.Console.Haskeline
  import System.Posix.Terminal

  getKey = runInputT defaultSettings (getInputChar "")

  main = do
    before <- getTerminalAttributes 0
    getKey >>= print
    after <- getTerminalAttributes 0
    print (before == after)

because there is no Eq instance for TerminalAttributes. So I asked stty:

  before=$(stty -a)
  ./test
  after=$(stty -a)
  if test "$before" = "$after"; then echo good; else echo bad; fi

and that reports "good".

So, perhaps a better answer to the OP would have been:

  import System.Console.Haskeline

then define

  getKey = runInputT defaultSettings (getInputChar "")

and use that instead of getChar.

Cheers
Ben



More information about the Haskell-Cafe mailing list