如何使Haskell程序根据用户输入显示初步结果?

如何使Haskell程序根据用户输入显示初步结果?,haskell,Haskell,我正在用Haskell编写一个程序,它反复地获取最近的结果,并使用这个结果来计算下一个结果。我希望能够看到响应用户输入的最新结果,因此我尝试了以下方法: main = mainhelper 0 mainhelper count = do count <- return (count + 1) line <- getLine if null line then do mainhelper count else do putStrLn $ show count

我正在用Haskell编写一个程序,它反复地获取最近的结果,并使用这个结果来计算下一个结果。我希望能够看到响应用户输入的最新结果,因此我尝试了以下方法:

main = mainhelper 0

mainhelper count = do
 count <- return (count + 1)
 line <- getLine
 if null line
  then do mainhelper count
  else do
   putStrLn $ show count
   return ()
main=mainhelper 0
mainhelper计数=do

count如果在不输入文本的情况下按enter键,它会返回一个空行——您只需立即提示输入更多内容,因此看起来可能什么都没有发生。但是如果您运行程序,按enter键三次,然后输入非空的内容,您将看到最终的
计数反映了多个条目

下面是代码的一个修改版本,它做了同样的事情,但稍微规范一些:

main = mainhelper 0

mainhelper count = do
  let count' = count + 1
  line <- getLine
  if null line
    then mainhelper count'
    else print count'

我使用的是后续函数
succ
,而不是显式的
+1
,后者只是一种样式首选项。

一个简单的解决方案是为复杂的计算提供一个线程,并通过
MVar
与主UI线程通信。例如:

import Control.Exception
import Control.Monad
import Control.Concurrent

thinkReallyHard x = do
    threadDelay 1000000 -- as a proxy for something that's actually difficult
    evaluate (x+1)

main = do
    v <- newMVar 0
    forkIO (forever (modifyMVar_ v thinkReallyHard))
    forever (getLine >> readMVar v >>= print)
导入控制。异常
进口管制
导入控制。并发
thinkReallyHard x=do
threadDelay 1000000——作为实际困难的代理
评估(x+1)
main=do
v>readMVar v>>=打印)

您可能想知道
evaluate
thinkReallyHard
中的作用。微妙之处在于,
MVar
s是懒惰的——它们可以像计算值一样轻松地包含thunk。特别是,这意味着很容易意外地将所有纯计算从分叉线程推送到正在读取和使用
MVar
内容的线程中。调用
evaluate
只是强制分叉线程在写入
MVar

之前完成纯计算,并不完全清楚您对getLine的期望。你想成为非阻塞的吗?也就是说,无论用户是否键入任何内容,总是立即返回?是的,如果用户未键入任何内容,我希望它立即返回空行。这不是任何语言中标准输入/输出的工作方式。哈斯克尔也不例外。如果它工作正常,就不可能编写一个以正常方式与用户交互的程序(获取一些输入、处理它、打印输出)。我想值得注意的是,当用户请求此版本中的当前值时,它会等到下一次迭代完成后再打印。这不难改变,但模块化程度稍低,而且一旦你有了使用多线程的想法,就不难了。谢谢!这正如所希望的那样,现在是我阅读相关模块的时候了。对不起,我不清楚,在这种情况下,我希望我的程序每次运行时都进入一个递增计数器的循环,我希望我的循环运行,无论我是否提供输入。我希望我的程序在输入时显示当前计数。因此,我希望在几分钟后输出10^7,而不是1。
import Control.Exception
import Control.Monad
import Control.Concurrent

thinkReallyHard x = do
    threadDelay 1000000 -- as a proxy for something that's actually difficult
    evaluate (x+1)

main = do
    v <- newMVar 0
    forkIO (forever (modifyMVar_ v thinkReallyHard))
    forever (getLine >> readMVar v >>= print)