Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 带状态的循环:为什么这个循环不';t形环_Haskell - Fatal编程技术网

Haskell 带状态的循环:为什么这个循环不';t形环

Haskell 带状态的循环:为什么这个循环不';t形环,haskell,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

我不明白为什么这个代码只循环一次然后退出? 在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 ()
类型TDeckSTIO=StateT tablexio
继续
putStrLn“是否继续?(是/否)”
c返回()

问题在于,当您键入
y
并按enter键时,实际上输入了两个字符:
'y'
本身,以及通过按回车键发送的换行符。第一次循环时,循环会看到
'y'
,但下一次循环时,它会看到
'\n'
,因为
'\n'
不是
'y'
,所以它会退出

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

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

evalStateT
类似于
runStateT
,但不包括最终状态,因此您不必使用
>return()

明确放弃值,这正是我想要的。当我刚刚更改代码并添加显示
\n
的打印时,我正在进行路径查找。感谢您提供liftIO$testLoop1 td->loop1的提示。这是我之前的测试之一,我想知道这两个代码中应该替换哪一个。evalState也很好。那是我第一次入侵statetransformer和IO。
testLoop1 = evalStateT loop1