質問

Haskellで簡単なプログラムを書いています。基本的に2つのシェルコマンドを並列に実行する必要があります。これがコード:

です
import System.Cmd
import System.Exit
import Control.Monad

exitCodeToBool ExitSuccess = True
exitCodeToBool (ExitFailure _) = False

run :: String -> IO Bool
run = (fmap exitCodeToBool) . system

main = liftM2 (&&) (run "foo") (run "bar")
.

でも "foo"コマンドはExitFailureを返し、 "bar"を実行することを期待しています。これはそうではありません!それらの両方が実行され、両方ともコンソールのエラーが表示されます。

と同時に

False && (all (/= 0) [1..])
.

は完全によく評価されます。これは、2番目の引数が計算されないことを意味します。私のアプリのシステムコマンドと同じことをどうやってもいいですか?

役に立ちましたか?

解決

条件付き実行のために&&を使用することは悪い習慣のものです。これは、副作用のないのようなもののためにこれを行う理由の問題のほんの問題の問題ですが、副作用がある場合は、そのような隠れた方法で依存するのはかなり軽蔑です。 (練習がとても広くなるため、ほとんどのプログラマーはすぐに認識します。しかし、それが私たちが励ますべきことだとは思わない。)

あなたが望むものは表現する方法です: "何らかの操作を実行する、False && all (/=0) [1..]を生成するまでを実行します"。

あなたの簡単な例では、明示的にそれをするでしょう:

main = do
   e0 <- run "foo"
   when e0 $ run "bar"
.

またはshort:False

これをより広範囲に使用したい場合は、より一般的な方法でそれをするのが良いです。単にブール状態をチェックすることは一般的ではありませんが、通常はある種の結果を渡したいと思うでしょう。結果を過ぎるのは、単にプリミティブアクションのリストではなく、IOのためにモナドを使用する主な理由です。

AHA、モナド!確かに、あなたが必要なものはIO MONADですが、追加の「キルスイッチ」を使用して:それぞれの行動を実行します。それぞれの結果を渡すことができますか、または - それらのいずれかが失敗した場合 - 全体を中止します。 run "foo" >>= (`when` run "bar")、右?

http://www.haskell.org/hoogle/hoogle/?hoogle=maybet

import Control.Monad.Trans.Maybe

run :: String -> MaybeT IO ()
run s = MaybeT $ do
   e <- system s
   return $ if exitCodeToBool e then Just () else Nothing

main = runMaybeT $ do
   run "foo"
   run "bar"
.

他のヒント

You say that you want to run commands in parallel and run "bar" only if "foo" succeeds. It makes no sense. You have to decide, if you want to run it in parallel or sequential.

If you want run "bar" only if "foo" succeed, try:

import System.Process

main = do callCommand "foo"
          callCommand "bar"

Or if you want to run it in parallel, try:

import System.Process
import Control.Concurrent


myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
    mvar <- newEmptyMVar
    forkFinally io (\_ -> putMVar mvar ())
    return mvar

main = do mvar <- myForkIO $ callCommand "foo"
          callCommand "bar"
          takeMVar mvar

The IO action

liftM2 f action1 action2

runs both actions for any binary function f is (e.g., (&&) in your case). If you want to just run action1 you can code it as follows:

--| Short-circuit &&
sAnd :: IO Bool -> IO Bool -> IO Bool
sAnd action1 action2 = do
    b <- action1
    if b then action2 else return False

Use it as sAnd action1 action2.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top