为交互式IO编写循环:编号和布局的问题

Mar*_*aro 12 io haskell loops

我刚开始使用Haskell,它让我感到困惑.我之前做过Java和Python,对我来说更有意义.

我正在尝试获取用户输入,检查它是否有效,如果没有:打印错误并再次获取输入; 如果有效:从中生成一个布尔值.

更确切地说,我想要一个是/否输入,其中'y'将产生True,'n'将产生False,并且任何其他输入将在命令行中打印消息并要求再次输入y/n.

例如:

Continue? y/n:
> assd
Invalid input.
Continue? y/n:
> y
(something happens)
Continue? y/n:
> n
(Close program)
Run Code Online (Sandbox Code Playgroud)

用farmiliar格式编写,这样的函数:

boolean inputBool() {
    while(True) {
       str = input("Continue? y/n: ");
       if (str == "y") {
           return True;
       } else if (str == "n") {
           return False;
       } else {
           print("Invalid input");
       }
}

--main program--

while(inputBool()) {
    doSomething();
}
Run Code Online (Sandbox Code Playgroud)

自从我刚开始使用haskell(今天实际上)以来,我不知道我能做什么或不能做什么.我在想类似的东西:

yesno :: Bool
yesno = do
        putStr "Continue? y/n: " 
        str <- readLn
        if (str == "y") then True else (
            if (str == "n") then False else (
                do
                putStrLn "Invalid input."
                yesno
            )    
        )
Run Code Online (Sandbox Code Playgroud)

哪个不起作用的原因有很多.我的主要问题是我不知道这个"做"是做什么的.我只是读它在需要io操作时使用并以某种方式执行以下表达式.在读完haskell后,一切都评估为一个值,这对我来说没有意义."做"评估的是什么?还有什么缩进预期?这似乎是随机的.我知道函数必须求值为我的布尔值,使用这个"do"操作似乎不可能.但是,如何将某些内容打印到控制台并仍然使其成为评估为True或False的表达式的一部分?

谢谢你的帮助.

(顺便问一下.互联网上有任何活跃的haskell论坛吗?我找不到任何= /)

pat*_*pat 22

由于你的函数需要执行IO,它必须在IOmonad中返回一个值,所以它的类型必须是yesno :: IO Bool,并且需要将TrueFalse值提升到monad中return.您还需要getLine代替readLn,因为您需要原始字符串,而不是解析的值(可能会出现解析错误).最后,您需要hFlush stdout在调用之前getLine,否则提示仍然会在缓冲区中等待换行(这需要您导入System.IO).

我已将提示字符串变为参数,因此您可以使用该函数询问各种是/否问题:

import System.IO

yesno :: String -> IO Bool
yesno prompt = do
          putStr $ prompt ++ " y/n: "
          hFlush stdout
          str <- getLine
          case str of
            "y" -> return True
            "n" -> return False
            _   -> do
              putStrLn "Invalid input."
              yesno prompt
Run Code Online (Sandbox Code Playgroud)

然后,您可以从交互循环中调用您的函数:

main :: IO ()
main = do
         fun <- yesno "Is Haskell fun?"
         if fun
          then putStrLn "rock on"
          else putStrLn "read more tutorials"
         continue <- yesno "Continue?"
         if continue then main else return ()
Run Code Online (Sandbox Code Playgroud)

  • 你必须注意"回归".它与Java或Python中的返回不同.在Haskell中,`return`在monadic shell中包含一个值,产生一个monadic值.它不会导致`do`块停止执行.通常,您会在`do`块中看到`return`作为叶子表达式,因此它将是从块返回的值. (2认同)