使用StateT循环:为什么此循环不循环

时间:2012-01-23 15:35:13

标签: haskell

我不明白为什么这段代码只循环一次然后退出? 在Ghci我只能回答第一个循环,然后似乎变量cont设置为false,我没有提示回答。

结果是:

*Main> testLoop1 td10
test
Do you want to continue? (y/N)
y
we continue
test
Do you want to continue? (y/N)
We stop

代码:

type TDeckSTIO    = StateT TableDecks IO

continue = do
putStrLn "Do you want to continue? (y/N)"
c <- getChar
return $ c == 'y'


loop1 :: TDeckSTIO () 
loop1 = do 
    liftIO $ putStrLn "test"
    cont<- liftIO continue 
    if cont
    then do 
        liftIO $ putStrLn "we continue"
        liftIO $ testLoop1 td

    else liftIO $ putStrLn "We stop"

testLoop1 td =  runStateT (loop1 ) td   >> return ()

1 个答案:

答案 0 :(得分:15)

问题在于,当您键入y并按Enter键时,实际上正在输入两个字符:'y'本身,以及通过按返回来发送的换行符键。第一轮,循环看到'y',但下一轮,它会看到'\n',而'\n'不是'y',它会退出。< / p>

您可以在进入循环之前执行hSetBuffering stdin NoBuffering(您需要导入System.IO),这样您就可以在不等待换行符的情况下处理字符,或者一次专门处理行:

continue = do
  putStrLn "Do you want to continue? (y/N)"
  s <- getLine
  return $ s == "y"

顺便说一下,您可以只使用liftIO $ testLoop1 td代替loop1,而不是写testLoop1,而是可以使用testLoop1 = evalStateT loop1 替换它。

另外,evalStateT最好写成:

runStateT

>> return ()与{{1}}类似,但不包含最终状态,因此您无需使用{{1}}明确丢弃该值。

相关问题