2013-06-06 4 views
14

Wenn ich eine Funktion habe, die IO Bool (speziell eine atomically) zurückgibt, gibt es eine Möglichkeit, den Rückgabewert direkt in der if-Anweisung ohne Bindung zu verwenden?Gibt es eine Möglichkeit, IO Bool in If-Anweisung ohne Bindung an einen Namen in Haskell zu verwenden?

Also zur Zeit habe ich

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

Ist es überhaupt möglich, dies als etwas zu schreiben, wie

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

Ich hatte gehofft, es eine Möglichkeit wäre anonym etwas wie <- zu verwenden also if (<- atomically ...) aber bisher kein solches Glück.

Ebenso auf getLine ist es möglich, so etwas wie

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

Verwandte Nachtrag zu schreiben - was ist die Art von (<-)? Ich kann es nicht in Ghci zeigen. Ich nehme an, es ist m a -> a, aber das würde bedeuten, dass es außerhalb einer Monade verwendet werden könnte, um dieser Monade zu entkommen, was unsicher wäre, oder? Ist (<-) überhaupt keine Funktion?

+6

Um Ihre letzte Frage zu beantworten, ist '(<-)' keine Funktion oder Ausdruck und ist eine eingebaute Syntax, die Teil der Do-Notation ist. Es entlädt sich zu einem Aufruf an "(>> =)" unter der Haube und Sie können [dies] (http://blog.sigfpe.com/2006/08/you-could-have-invened-monads-and) lesen. html), um mehr darüber zu erfahren, wie Entzuckerung funktioniert. –

Antwort

15

Sie können ifM von Control.Conditional verwenden, wenn das Ihrem Zweck entspricht und es nicht einmal schwer ist, eine ähnliche Funktion zu schreiben.

Nur um Ihnen Beispiel

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") 

Ich denke, es gibt Möglichkeiten, rebindable Syntaxerweiterung verwenden, die Sie auch if c then e1 else e2 wie Syntax für ifM verwenden können, aber es ist nicht der Mühe wert, das zu versuchen.

1

Nein, das geht nicht. Nun, um ehrlich zu sein, es gibt einen "Hack", der es Ihnen erlaubt, zumindest Code wie diesen zu schreiben und ihn kompilieren zu lassen, aber die Ergebnisse werden mit ziemlicher Sicherheit nicht das sein, was Sie wollten oder erwarteten.

Warum ist das nicht möglich? Nun, zum einen enthält ein Wert vom Typ IO Bool in keiner Weise einen Wert vom Typ Bool. Es ist vielmehr eine "Aktion", die bei Ausführung einen Wert vom Typ Bool zurückgibt. Zum anderen, wenn dies möglich wäre, würde es Ihnen erlauben, Nebenwirkungen innerhalb von reinem Code zu verbergen. Dies würde einen Kern von Haskell verletzen. Und Haskell ist sehr prinzipientreu.

+3

Ich glaube nicht, dass das genau ist. Sein ursprünglicher Code verwendet eindeutig do-notation, was bedeutet, dass die Ergebnisse der if-Anweisung bereits in IO sind.Mein Verständnis ist, dass er nur einen Operator wie '<$>' oder '>> =' für Funktionen verwenden möchte, die nur mit der if-Anweisung funktionieren würden. –

+0

Es ist mir nicht klar, was Sie für ungenau halten. Wenn Sie glauben, dass etwas wie das, was OP fragt, möglich ist (mit dem Ausdruck 'if'), geben Sie ein Beispiel an. –

4

Mit GHC 7.6 und der LambdaCase Spracherweiterung können Sie

 
{-# LANGUAGE LambdaCase #-} 

import System.Directory 

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

schreiben Es ist nicht genau if..then..else, aber näher genug, erfordert nicht auf das Ergebnis bindend, und einige Leute (mich nicht) sagen, dass if..then..else ist sowieso ein schlechter Stil in Haskell.