Vlad the Impala
Vlad the Impala

Reputation: 15872

Using fmap with a maybe when a function uses IO

I have a function that I want to use a Maybe val with. Usually I would do func <$> val. But now suppose that func uses the IO monad. func <$> val will return a Maybe (IO ()). So instead I had to define a new operator:

(<$$>) :: Monad m => (a -> m b) -> Maybe a -> m ()
(<$$>) func (Just val) = func val >> return ()
(<$$>) func Nothing    = return ()

So now I can write func <$$> val, but is there a better way to do it?

Upvotes: 5

Views: 267

Answers (4)

Ganesh Sittampalam
Ganesh Sittampalam

Reputation: 29100

mapM_ from Data.Foldable is probably the best match:

Prelude Data.Foldable> :set -XScopedTypeVariables
Prelude Data.Foldable> :t \f (a :: Maybe a) -> Data.Foldable.mapM_ f a
\f (a :: Maybe a) -> Data.Foldable.mapM_ f a
  :: Monad m => (a -> m b) -> Maybe a -> m ()

If you'd like a more specialised type there's also maybe:

Prelude> :t \f -> maybe (return ()) (f $)
\f -> maybe (return ()) (f $)
  :: Monad m => (a -> m ()) -> Maybe a -> m ()

Upvotes: 3

shang
shang

Reputation: 24802

Your <$$> is traverse_ from Data.Foldable.

Upvotes: 1

leftaroundabout
leftaroundabout

Reputation: 120711

If you have a lot of this in your code, it might be worth employing the MaybeT transformer:

   (\func val -> liftIO . func =<< MaybeT (return val) ) 
        :: (a -> IO b) -> Maybe b -> MaybeT IO b

That doesn't immediately bring you any further than plain IO (Maybe ()), but it composes nicely.

Upvotes: 0

Sassa NF
Sassa NF

Reputation: 5406

Is a one-liner always better? Here's how purity of undefined can be useful:

(<$$>) g x = maybe (return undefined) g x >> return ()

Example:

 Prelude> print <$$> (Just 1)
 1
 Prelude> print <$$> Nothing
 Prelude>

Upvotes: 0

Related Questions