Мне интересно, есть ли идиоматический способ написать управляющий код, похожий на прикованные if/else заявления на императивном языке в IO Monad.Связанные строки if/else в IO Monad
Таким образом, в языке, как 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
, потому что это ближе к императивная версия.
но даже в питона вы должны реорганизовать те;) – Carsten
ОК, я укушу, Как? :) – ynimous
Ну, вы можете сделать что-то вроде создания списка действий и использовать такие вещи, как 'foldM' или' forM' и т. Д., Чтобы получить нужный результат. Это будет обобщать на любое количество 'elif', хотя это было бы громоздким только для 3 случаев. То же самое было бы верно в python: 'test, action в tests_and_actions: if test (input): action (input)'. – Bakuriu