Mi chiedo se esiste un modo idiomatico di scrivere il codice di controllo simile alle dichiarazioni concatenate se/else in un linguaggio imperativo nell'IO Monade.Concatenato se/else staments nell'IO Monade
Quindi, in un linguaggio come Python, vorrei qualcosa di tipicamente destra come questo:
if οs.path.isdir(fname):
# do whatever
elif os.path.isfile(fname):
# ...
else:
# ...
il meglio che potessi venire in Haskell è la seguente:
isf <- doesFileExist path
isd <- if isf then return False else doesDirectoryExist path
case (isf, isd) of
(True, _) -> return ...
(_, True) -> return ...
_ -> return ...
che non è così buono e mi chiedo se c'è un modo migliore per scrivere questo genere di cose.
Inoltre, per convalidare la mia comprensione: la parte è richiesta nel caso della Monade IO, se non si desidera eseguire sempre entrambe le operazioni. La mia ipotesi sarebbe che in altre Monadi (Monad Lazy?), Questo non sarebbe necessario perché isd
sarebbe valutato pigramente.
Modifica
Sulla base dei primi commenti, ho finito con il seguente:
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"
che è simile al secondo suggerimento @ di chi, po preferisco ifM
, perché è più vicino al versione imperativa.
ma anche in python si dovrebbe refactoring quelli;) – Carsten
OK, sarò morso, come? :) – ynimous
Beh, si potrebbe fare qualcosa come costruire un elenco di azioni e usare cose come 'foldM' o' forM' ecc. Per ottenere il risultato desiderato. Questo sarebbe generalizzato a qualsiasi numero di 'elif's anche se sarebbe ingombrante solo per 3 casi. Lo stesso sarebbe vero in Python: 'per test, azione in test_and_actions: se test (input): action (input)'. – Bakuriu