Haskell 中的 '\b' 字符如何工作?

F. *_*Zer 4 haskell

资料来源:格雷厄姆·赫顿。“ Haskell 编程”(第 180 页)

\n
\n
    \n
  1. 使用getCh,定义一个readLine :: IO String与 getLine 行为方式相同的操作,不同之处在于它还允许使用删除键删除字符。
  2. \n
\n
\n
\n

提示:删除字符为\xe2\x80\x99\\ DEL\xe2\x80\x99,光标后移一格的控制字符为\xe2\x80\x99\\b\xe2\x80\x99

\n
\n

我使用一个\'\\b\'角色解决了这个练习,但在网上发现解算器使用了两个角色。为什么这个问题的解决者使用"\\b \\b"而不是"\\b"?似乎是一个错字,但我不确定。我发现它适用于三个\'\\b\'角色。

\n

这个角色是如何运作的?

\n
import System.IO\n\ngetCh :: IO Char\ngetCh = do\n  hSetEcho stdin False\n  x <- getChar\n  hSetEcho stdin True\n  return x\n\nreadLine :: IO String\nreadLine = readLine\' ""\n\nreadLine\' :: String -> IO String\nreadLine\' xs = do\n  x <- getCh\n  case x of\n    \'\\n\' -> do\n      putChar \'\\n\'\n      return xs\n    \'\\DEL\' ->\n      if null xs\n        then readLine\' ""\n        else do\n          putStr "\\b \\b"\n          readLine\' (init xs)\n    _ -> do\n      putChar x\n      readLine\' (xs ++ [x])\n
Run Code Online (Sandbox Code Playgroud)\n

lef*_*out 7

如果您仅使用"\\b",光标将移至左侧,但不会删除那里看到的字符,直到您用新的按键输入覆盖它。例如,FOO\xe2\x86\x90最终你会得到fo\xe2\x81\x81o,但这会产生误导:如果你没有按另一个字母键而是立即按下\xe2\x86\xb5,那么结果看起来仍然是foo,而实际上它只是fo

\n

为了避免这种情况,解决方案"\\b \\b"向左移动,用空格覆盖字符以可视化删除它,然后立即再次向左移动。这与向左移动一次并就地删除字符具有相同的效果。

\n


ber*_*eal 6

\b将光标向后移动一个字符,但不会删除它(至少在大多数终端上不会)。例如,字符串abcde\b将显示为abcde,字符串将显示abcde\bfabcdf。这就是为什么序列显式地\b \b用空格覆盖最后一个字符,然后再次将光标移回。