Haskell: REPL 的 for 循环

Haskell: a for loop for a REPL

我正在尝试在 Haskell 中编写类似 repl 的东西,我想在 C:

中复制此代码
for (int c = getc(stdin); c != 'e'; c = getc(stdin)) {
        printf("I got %c!\n", c);
}

我可以使用递归,但我担心超出限制。

应该使用递归。 Haskell 旨在无限制地处理递归,递归可以而且应该用于有效的无限循环(例如,事件处理循环或 REPL 循环)。

因此,您可以或多或少地编写如下程序:

main = do
  txt <- getLine
  if txt /= "exit" then do
    putStrLn $ "I got " ++ txt ++ "!"
    main
  else do
    return ()

给予:

$ ./repl
foo
I got foo!
bar
I got bar!
exit
$ 

我编写它是为了抓取整行输入而不是单个字符,因为在尝试逐字符抓取输入时缓冲输入通常会出现问题。这种无限递归工作正常,无论它在退出前处理了多少亿行都不会超过任何限制。

在大多数 real-world 程序中,您不希望整个主程序循环,因此您通常会编写如下内容。在这里,我使用了 when ,这是一种更好看的方式来编写模式 if xxx then yyy else return ().

import Control.Monad  -- for definition of "when"

main = do
  -- initialization
  putStrLn $ "Welcome to my REPL!"
  -- start the main loop
  loop
  -- clean up
  putStrLn $ "Thanks so much for using my REPL!"

-- definition of main loop
loop = do
  txt <- getLine
  when (txt /= "exit") $ do
    putStrLn $ "I got " ++ txt ++ "!"
    loop