ridiculous_fish
ridiculous_fish

Reputation: 18541

How to avoid superfluous variables in do notation?

Say in a Haskell do-notation block, I wish to have a variable is_root indicating if I am root:

import System.Posix.User
main = do
    uid <- getRealUserID
    is_root <- return $ uid == 0

That annoying uid variable is only used in that one place. I wish instead I could write this:

main = do
    is_root <- getRealUserID == 0

But of course that won't compile.

How can I get rid of superfluous variables like uid? Here's the best I've come up with:

import System.Posix.User
main = do
    is_root <- getRealUserID >>= return . ((==) 0)

Blech! Is there a nicer way?

Upvotes: 16

Views: 596

Answers (2)

Lambdageek
Lambdageek

Reputation: 12475

(I assume your goal is to limit the scope of uid, not to just be pointfree for its own sake)

In a simple case like this, @pdw's answer is probably the way to go. The operators <$> and <*> from Control.Applicative are particularly helpful here.

foo = do
  are_same <- (==) <$> doThis <*> doThat

In slightly more complicated situations, you could use a nested-do:

complicatedEq :: This -> That -> IO Bool

main = do
  are_same <- do
    this <- doThis
    that <- doThatBasedOn this
    complicatedEq this that
  ... rest ...

Anything significantly long probably deserves to be its own function.

Upvotes: 6

pdw
pdw

Reputation: 8866

One way is

fmap (== 0) getRealUserID

Upvotes: 23

Related Questions