Haskell - Do while循环

7

我刚接触Haskell,希望有人能帮忙!我试图让这个程序使用do while循环。

第二个getLine命令的结果会被放入变量goGlenn中,如果goGlenn不等于"start",则程序将返回到开头。

    start = do
    loop $ do lift performAction
        putStrLn "Hello, what is your name?"
        name <- getLine
        putStrLn ("Welcome to our personality test " ++ name ++ ", inspired by the Big Five Theory.") 
        putStrLn "You will receive fifty questions in total to which you can reply with Yes or No."
        putStrLn "Whenever you feel ready to begin please write Start"
        goGlenn <- getLine
        putStrLn goGlenn
    while (goGlenn /= "start")

补充@chi的回答,您编写的代码基本上是正确的Haskell语法,但像“loop”和“while”这样的东西不是内置的。Haskell实际上没有do-while循环,它具有递归可以用来实现do-while循环。 Haskell实际上根本没有循环,只有递归,您将不得不学习如何重新实现您所使用的命令式语言的功能。 - bheklilr
@bheklilr,我想Gallais在他们下面的评论中是正确的:上面的代码似乎是从Control.Monad.LoopWhile文档中改编而来的。 - chi
2个回答

15
在Haskell中,你通常使用递归的方式来编写"循环"。
import Control.Monad

-- ....

start = do
    putStrLn "Before the loop!"
    -- we define "loop" as a recursive IO action
    let loop = do
            putStrLn "Hello, what is your name?"
            name <- getLine
            putStrLn $ "Welcome to our personality test " ++ name 
                     ++ ", inspired by the Big Five Theory."
            putStrLn "You will receive fifty questions in total to which you can reply with Yes or No."
            putStrLn "Whenever you feel ready to begin please write Start"
            goGlenn <- getLine
            putStrLn goGlenn
            -- if we did not finish, start another loop
            when (goGlenn /= "start") loop
    loop  -- start the first iteration 
    putStrLn "After the loop!"

2
我猜测 OP 正试图使用 loop-while(请参见代码摘录的相似之处)。看到导入列表会更有帮助。 - gallais
@gallais 很有趣,我之前不知道这个... 不过,我还是想知道原帖作者是否真的想使用那个库,或者只是想达到相同的效果。对于初学者,我建议先学习基本方法。 - chi
2
与其写let loop = ...; loop,我更喜欢写fix $ \loop -> ...。当然这只是纯粹的风格问题。 - user2407038

3

不确定,也许这个版本可以帮助你:

import Control.Monad

loop action = do
    condition <- action
    when condition (loop action)

while = return

start =
    let action = do {
        putStrLn "Hello, what is your name?";
        name <- getLine;
        putStrLn ("Welcome to our personality test " ++ name ++ ", inspired by the Big Five Theory.");
        putStrLn "You will receive fifty questions in total to which you can reply with Yes or No.";
        putStrLn "Whenever you feel ready to begin please write Start";
        goGlenn <- getLine;
        putStrLn goGlenn;
        while (goGlenn /= "start");
    }
    in loop action

(Edit) 或者也可以是:
start =
    loop (do {
        putStrLn "Hello, what is your name?";
        name <- getLine;
        putStrLn ("Welcome to our personality test " ++ name ++ ", inspired by the Big Five Theory.");
        putStrLn "You will receive fifty questions in total to which you can reply with Yes or No.";
        putStrLn "Whenever you feel ready to begin please write Start";
        goGlenn <- getLine;
        putStrLn goGlenn;
        while (goGlenn /= "start");
    })        

如果我们定义一个自定义 helper 函数 loop,我会尝试将 action 的定义内联,并直接编写 loop $ do ... - chi
但是没有问题...(我认为是这样)请检查答案中的编辑 - Ivan David
是的,两种方式都是正确的。第二种方式更加优美,至少对我来说如此。 - chi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接