Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 751
ridiculous_fish Avatar asked Aug 14 '14 18:08

ridiculous_fish


Video Answer


2 Answers

One way is

fmap (== 0) getRealUserID
like image 115
pdw Avatar answered Oct 14 '22 10:10

pdw


(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.

like image 38
Lambdageek Avatar answered Oct 14 '22 11:10

Lambdageek