我编写了这个程序,我编译了:
ghc --make shell.hs
当我运行时,它看起来像是:
$./shell
enter your number:
6
6
okay... it execute 6 time...
如果我删除sleep 2
语句,则会快速退出但仅输出6
。
我尝试按照类似问题at this answer的建议(这是下面代码中的内容)但是没有用。
它没有执行所有命令似乎很奇怪。如何强制它以严格的顺序执行所有命令?懒惰是一个很好的功能,但是当谈到 IO 时,它只是糟透了,或者我不够专家来理解它。
我想要做的是按严格的顺序从列表中执行所有命令,我不希望 Haskell “智能地”代表我删除一些命令(如果我想在shell中执行sleep 2秒,我应该被允许这样做。)
如果必须使用waitForProcess
解决此问题,那么我的问题是我不知道如何使用它。我试过谷歌,但没有看到一个简单的例子。
请注意,我想为下面给出的程序代码提供一个有效的代码解决方案,应该有一个合理的保证,程序在典型的Linux(比如Debian 7)上运行的bash上按预期工作下面给出了Python 程序。
import System.Process
import System.Exit
main = do
putStrLn "enter your number:"
n <- getLine
main1 (readInt n)
putStrLn ("okay... it execute " ++ n ++" time...")
readInt:: String -> Int
readInt = read
main1 n = do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
if n == 0 then (main1 (n-1)) else return ()
以下是 Python 程序,它可以根据需要使用正确的sleep
:
import os
for i in range(6):
os.system("echo " + str(i))
os.system("sleep 2")
答案 0 :(得分:3)
如何使用forM_
编写更多类似Python的版本:
import Control.Monad
main1 n = do
forM_ [n,n-1 .. 1] $ \n -> do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
return ()
答案 1 :(得分:0)
该计划正在做你告诉他要做的事情:
main1 n = do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
if n == 0 then (main1 (n-1)) else return ()
此处我们有n == 6
因此if
的条件为false,然后执行return ()
,这会终止main1
无效。
请注意,如果您传递了n == 0
,则条件为真,它将执行main1 (-1)
然后停止。在任何情况下,main1
将不重复命令n
次,它将始终执行一次(如果n /= 0
)或两次(如果n == 0
)。
您可以通过执行以下操作来解决此问题:
main1 n = do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
if n > 0 then main1 (n-1) else return ()
或等同地:
import Control.Monad
main1 n = do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
when (n > 0) $ main1 (n-1)
这里的问题是你使用一般递归来重复给定的语句。但是一般递归可以做任何事情,因此您可以轻松地产生错误(如您的情况)。为避免这种情况,使用其他函数构建代码通常很有用。例如:
main1 n = sequence_ $ map execute [1..n]
execute i = do
ExitSuccess <- system $ "echo" ++ show i
ExitSuccess <- system $ "sleep 2"
return ()
或者:
main1 n = mapM_ execute [1..n]
您知道mapM_
和[1..n]
做了什么,因此组合它们会告诉您execute
行动将被执行n
次。
在任何情况下IO
monad 保证操作都按顺序执行,所以你不应该将Haskell懒惰归因于代码没有被执行的事实预期的次数。
懒惰和输入/输出的问题是不同的。