Haskell 没有执行所有外部 shell 命令
Haskell not executing all external shell commands
我写了这个程序并编译了:
ghc --make shell.hs
当我运行它看起来像:
$./shell
enter your number:
6
6
okay... it execute 6 time...
如果我删除 sleep 2
语句,它会快速退出但只输出 6
.
我尝试按照类似问题 at this answer 给出的建议(即下面代码中的内容)进行操作,但没有成功。
似乎很奇怪,它没有执行所有的命令。我如何强制它以严格的顺序执行所有命令?懒惰是一个很好的特性,但是当涉及到 IO 时,它就很糟糕,或者我不是一个足够的专家来理解它。
我想做的是以严格的顺序执行列表中的所有命令,我不想 Haskell 到 "intelligently" 删除一些代表我的命令(如果我想在 shell 中执行 sleep 2 秒,我应该被允许这样做)。
如果必须使用waitForProcess
来解决这个问题,那么我的问题是我不知道如何使用它。我试过 google 但没有看到一个简单的例子。
请注意,我想要一个适用于我在下面给出的程序代码的工作代码解决方案,并且应该合理保证该程序在 bash 运行ning 上按预期正常工作Linux(例如,Debian 7)作为下面给出的 Python 程序 运行s.
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")
使用 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 ()
该程序正在执行您要他执行的操作:
main1 n = do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
if n == 0 then (main1 (n-1)) else return ()
这里有 n == 6
,所以 if
的条件为假,然后 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 懒惰代码没有执行预期的次数。
懒惰的问题和input/output不一样
我写了这个程序并编译了:
ghc --make shell.hs
当我运行它看起来像:
$./shell
enter your number:
6
6
okay... it execute 6 time...
如果我删除 sleep 2
语句,它会快速退出但只输出 6
.
我尝试按照类似问题 at this answer 给出的建议(即下面代码中的内容)进行操作,但没有成功。
似乎很奇怪,它没有执行所有的命令。我如何强制它以严格的顺序执行所有命令?懒惰是一个很好的特性,但是当涉及到 IO 时,它就很糟糕,或者我不是一个足够的专家来理解它。
我想做的是以严格的顺序执行列表中的所有命令,我不想 Haskell 到 "intelligently" 删除一些代表我的命令(如果我想在 shell 中执行 sleep 2 秒,我应该被允许这样做)。
如果必须使用waitForProcess
来解决这个问题,那么我的问题是我不知道如何使用它。我试过 google 但没有看到一个简单的例子。
请注意,我想要一个适用于我在下面给出的程序代码的工作代码解决方案,并且应该合理保证该程序在 bash 运行ning 上按预期正常工作Linux(例如,Debian 7)作为下面给出的 Python 程序 运行s.
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")
使用 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 ()
该程序正在执行您要他执行的操作:
main1 n = do
ExitSuccess <- system ("echo " ++ (show n))
ExitSuccess <- system "sleep 2"
if n == 0 then (main1 (n-1)) else return ()
这里有 n == 6
,所以 if
的条件为假,然后 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 懒惰代码没有执行预期的次数。
懒惰的问题和input/output不一样