2013-06-06 16 views
14

Se ho una funzione che restituisce IO Bool (in particolare uno atomically), esiste un modo per utilizzare direttamente il valore restituito nell'istruzione if, senza l'associazione?Esiste un modo per utilizzare IO Bool nell'istruzione if senza legarsi a un nome in haskell?

Quindi attualmente ho ho

ok <- atomically $ do 
    ... 
if (ok) then do 
    ... 
else do 
    ... 

È a tutto il possibile per scrivere questo come qualcosa di simile

if (*some_operator_here* atomically $ do 
     ...) then do 
    ... 
else do 
    ... 

Speravo ci sarebbe un modo per usare qualcosa come <- anonimo , ovvero, if (<- atomically ...) ma finora non ha avuto tanta fortuna.

Allo stesso modo il GetLine, è possibile scrivere qualcosa di simile

if ((*operator* getLine) == "1234") then do ... 

addendum correlati - qual è il tipo di (<-)? Non riesco a farlo apparire in ghci. Suppongo che sia m a -> a, ma questo significherebbe che potrebbe essere usato al di fuori di una monade per sfuggire a quella monade, che non sarebbe sicura, giusto? (<-) non ha alcuna funzione?

+6

Per rispondere alla tua ultima domanda, '(<-)' non è una funzione o un'espressione ed è una sintassi incorporata che fa parte della notazione "do". È desugars per una chiamata a '(>> =)' sotto il cofano e si può leggere [questo] (http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and. html) per saperne di più su come funziona il desugaring. –

risposta

15

È possibile utilizzare ifM da Control.Conditional se questo è adatto al proprio scopo e non è nemmeno difficile scrivere una funzione simile.

solo per darvi esempio

import Control.Conditional 
import Control.Monad 

(==:) :: (Eq a,Monad m) => m a -> m a -> m Bool 
(==:) = liftM2 (==) 

main = ifM (getLine ==: getLine) (print "hit") (print "miss") 

Penso che ci siano modi utilizzando la sintassi estensione rebindable che si può anche utilizzare come if c then e1 else e2 sintassi per ifM, ma non vale la pena di provare questo.

1

No, non è possibile. Beh, ad essere onesti, c'è un 'hack' che ti permetterà almeno di scrivere codice come questo e farlo compilare, ma i risultati quasi certamente non saranno ciò che volevi o aspettavi.

Perché non è possibile? Bene, per una cosa un valore di tipo non contiene in alcun modo un valore di tipo Bool. Piuttosto è un 'azione' che quando eseguita restituirà un valore di tipo Bool. Per un'altra cosa, se fosse possibile, ti permetterebbe di nascondere gli effetti collaterali all'interno di quello che sembra essere puro codice. Ciò violerebbe un principio di base di Haskell. E Haskell è molto guidato.

+3

Non penso che sia accurato. Il suo codice originale sta chiaramente usando la notazione, il che significa che i risultati dell'istruzione if sono già in IO come appropriato.La mia comprensione è che vuole solo usare qualche operatore come "<$>" o ">> =" per le funzioni che funzionano solo con l'istruzione if. –

+0

Non mi è chiaro cosa pensi sia impreciso. Se credi che qualcosa di simile a ciò che OP stava chiedendo è possibile (usando l'espressione 'if'), per favore fai un esempio. –

4

Con GHC 7.6 e l'estensione LambdaCase lingua, è possibile scrivere

 
{-# LANGUAGE LambdaCase #-} 

import System.Directory 

main = do 
    doesFileExist "/etc/passwd" >>= \case 
     True -> putStrLn "Yes" 
     False -> putStrLn "No" 

Non è esattamente if..then..else, ma abbastanza vicini, non richiede il legame con il risultato, e alcune persone (non io) dire che if..then..else è in ogni caso un cattivo stile in Haskell.

Problemi correlati