コマンド ラインで 2 つの整数を受け取り、それらを使って何か面白いことを行うプログラムを作成しようとしています。整数の読み取り/解析は、比較的単純なコードである必要があるため、できるだけ簡単かつ命令的に記述したいと考えています。
私が直面している問題は、Haskell ではエラー処理がそれほど単純ではないということです。Haskellではパターンマッチングがよく使われているようです。これにより、命令型バージョンよりもコードを理解するのが少し難しくなっているようです。
プログラムは次のように実行されます (この例では、2 つの数値を加算するだけです)。
$ ./my_prog
ERROR: Must run like `./my_prog NUM_A NUM_B`.
$ ./my_prog cat 1
ERROR: Could not parse NUM_A "cat" as integer
$ ./my_prog 10 dog
ERROR: Could not parse NUM_B "dog" as integer
$ ./my_prog 10 1
11
命令型疑似 Python でやりたいことは次のとおりです。
function die (errorMessage):
print("ERROR: %s" % errorMessage)
sys.exit(1)
function main ():
if len(sys.argv) != 2:
die("Must run program like `%s NUM_A NUM_B`" % sys.progname)
num_a = 0
num_b = 0
try:
num_a = int(sys.argv[0])
except:
die("Could not parse NUM_A \"%s\" as integer" % sys.argv[0])
try:
num_b = int(sys.argv[1])
except:
die("Could not parse NUM_B \"%s\" as integer" % sys.argv[1])
doSomethingInteresting(num_a, num_b)
function doSomethingInteresting (num_a, num_b):
print(num_a + num_b)
Python では、基本的に main 関数を上から下に読むことができ、すべてのエラー処理は簡単です。 複数のパターン マッチングを行わずに、Haskell でこのシンプルで直接的なエラー処理を実装する方法はありますか?
これは私が思いついた Haskell コードで、これと同じタスクを実行しますが、パターン マッチング セクションが複数あるため、Python コードよりもはるかに複雑に見えます。
module Main ( main
)
where
import System.Environment (getArgs, getProgName)
import System.Exit (ExitCode(..), exitWith)
import Text.Read (readMaybe)
die :: String -> IO a
die err = do putStrLn $ "ERROR: " ++ err
exitWith (ExitFailure 1)
main :: IO ()
main = do
args <- getArgs
progName <- getProgName
case args of
[strNumA, strNumB] -> do
let maybeNumA = readMaybe strNumA :: Maybe Int
maybeNumB = readMaybe strNumB :: Maybe Int
checkMaybeArgs strNumA maybeNumA strNumB maybeNumB
_ -> die ("Must run like `" ++ progName ++ " NUM_A NUM_B`.")
where
checkMaybeArgs :: String -> Maybe Int -> String -> Maybe Int -> IO ()
checkMaybeArgs badStrNumA Nothing _ _ =
die ("Could not parse NUM_A \"" ++ badStrNumA ++ "\" as integer")
checkMaybeArgs _ _ badStrNumB Nothing =
die ("Could not parse NUM_B \"" ++ badStrNumB ++ "\" as integer")
checkMaybeArgs _ (Just numA) _ (Just numB) = doSomethingInteresting numA numB
doSomethingInteresting :: Int -> Int -> IO ()
doSomethingInteresting numA numB = print $ numA + numB
(また、私の Haskell スタイルに他に何か問題がある場合は、修正していただければ幸いです。)
編集: 最近、Haskell で例外を処理するさまざまな方法について説明しているブログ記事を見つけました。それは多少関連しています:
http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways-to-report-errors