Reputation: 10781
If I've got a function that returns IO Bool
(specifically an atomically
), is there any way to use the return value directly in the if
statement, without binding?
So currently I've got
ok <- atomically $ do
...
if (ok) then do
...
else do
...
Is it at all possible to write this as something like
if (*some_operator_here* atomically $ do
...) then do
...
else do
...
I was hoping there'd be a way to use something like <-
anonymously, i.e., if (<- atomically ...)
but so far no such luck.
Similarly on getLine, is it possible to write something like
if ((*operator* getLine) == "1234") then do ...
Related addendum--what is the type of (<-)
? I can't get it to show up in ghci. I'm assuming it's m a -> a
, but then that would mean it could be used outside of a monad to escape that monad, which would be unsafe, right? Is (<-)
not a function at all?
Upvotes: 16
Views: 6453
Reputation: 25763
With GHC 7.6 and the LambdaCase
language extension, you can write
{-# LANGUAGE LambdaCase #-} import System.Directory main = do doesFileExist "/etc/passwd" >>= \case True -> putStrLn "Yes" False -> putStrLn "No"
It is not exactly if..then..else
, but closer enough, does not require binding to the result, and some people (not me) say that if..then..else
is bad style in Haskell anyways.
Upvotes: 8
Reputation: 11208
You can use ifM
from Control.Conditional
if that suits your purpose and its not even hard to write a similar function.
Just to give you example
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")
I think there are ways using rebindable syntax extension that you can even use if c then e1 else e2
like syntax for ifM
but it is not worth the effort to try that.
Upvotes: 17
Reputation: 12077
No, you cannot. Well, to be honest, there is a 'hack' that will allow you to at least write code like this and get it to compile, but the results will almost certainly not be what you wanted or expected.
Why is this not possible? Well, for one thing a value of type IO Bool
does not in any sense contain a value of type Bool
. Rather it is an 'action' that when performed will return a value of type Bool
. For another thing, if this were possible, it would allow you to hide side-effects inside what appears to be pure code. This would violate a core principal of Haskell. And Haskell is very principled.
Upvotes: 1