我想知道是否有一種習慣方式來編寫類似於IO Monad中命令式語言中的鏈式if/else語句的控制代碼。在IO Monad中鏈接if/else腳本
在像Python語言所以,我通常會正確的是這樣的:
if οs.path.isdir(fname):
# do whatever
elif os.path.isfile(fname):
# ...
else:
# ...
最好我能想出在Haskell如下:
isf <- doesFileExist path
isd <- if isf then return False else doesDirectoryExist path
case (isf, isd) of
(True, _) -> return ...
(_, True) -> return ...
_ -> return ...
這是不一樣好,我想知道是否有更好的方法來寫這種事情。
此外,爲了驗證我的理解:如果您不想始終執行這兩個操作,則IO Monad的情況下需要if isf
部分isd <- ...
。我的猜測是,在其他單子(懶惰單子?),這將不會被需要,因爲isd
將被評估懶惰。
編輯
基於第一意見,我結束了以下內容:
firstMatchM :: (Monad m) => a -> [(a -> m Bool, b)] -> b -> m b
firstMatchM arg [] def = return def
firstMatchM arg ((check,x):xs) def = do
t <- check arg
if t then return x else firstMatchM arg xs def
doFirstM :: (Monad m) => a -> [(a -> m Bool, a -> m b)] -> (a -> m b) -> m b
doFirstM arg acts def = do
fm <- firstMatchM arg acts def
fm arg
handlePath2 path = doFirstM path
[(\p -> doesFileExist p,
\p -> return "file"
),(\p -> doesDirectoryExist p,
\p -> return "dir"
)] $ \p -> return "Error"
這類似於@卡的第二個建議,有點我喜歡ifM
,因爲它更接近命令版本。
但即使在Python,你應該重構這些;) – Carsten
OK,我會咬,怎麼樣? :) – ynimous
那麼,你可以做一些事情,比如建立一個動作列表,使用'foldM'或'forM'等東西來獲得你想要的結果。這會推廣到任何數量的elif,儘管只有3個案例會很麻煩。在python中也是如此:'test,test_and_actions中的動作:if test(input):action(input)'。 – Bakuriu