I am trying to compose some IO wrapped functions.
My current code (that works) is:
getUserHome :: IO String
getUserHome = do
usr_id <- getRealUserID
homeDirectory <$> getUserEntryForID usr_id
What I am looking for is a more convenient notation (one without using the do
-keyword).
Without any of the Monadic salad I would just write
getUserHome = homeDirectory . getUserEntryForID . getRealUserID
I would guess there is an alternative operator for the .
that respects the Monad ..? But in all my searching, I have not found it.
I tried <$>
but that does not seem to be what i want:
src/Main.hs:49:21: error:
• Couldn't match type ‘IO UserEntry’ with ‘UserEntry’
Expected type: UserID -> UserEntry
Actual type: UserID -> IO UserEntry
• In the second argument of ‘(<$>)’, namely ‘getUserEntryForID’
In the first argument of ‘(<$>)’, namely
‘homeDirectory <$> getUserEntryForID’
In the expression:
homeDirectory <$> getUserEntryForID <$> getRealUserID
|
49 | homeDirectory <$> getUserEntryForID <$> getRealUserID -- usr_id
You can use >>=
, since Haskell eventually "desugars" the do
block to this:
getUserHome :: IO String
getUserHome = getRealUserID >>= \usr_id -> homeDirectory <$> getUserEntryForID usr_id
this can be simplified with:
getUserHome :: IO String
getUserHome = getRealUserID >>= fmap homeDirectory . getUserEntryForID
or:
getUserHome :: IO String
getUserHome = getRealUserID >>= (homeDirectory <$>) . getUserEntryForID