# Pastebin snDGzEnC import Data.Maybe (fromMaybe) import Data.Functor ((<&>)) -- given: f :: String -> IO String f = undefined g :: String -> Maybe String g = undefined -- All of the below are equivalent, use the one that makes the most -- sense to you. Your tastes will probably shift as you learn more -- Haskell and become more confident with the types in play. -- when in doubt, just use `do` and then refine it if you feel like it justUseDo :: String -> IO String justUseDo str = do str' <- f str case g str' of Nothing -> pure str' -- from f Just str'' -> pure str'' -- from g if it exists -- using `maybe` function instead of explicit pattern match maybeFunction :: String -> IO String maybeFunction str = do str' <- f str maybe (pure str') pure $ g str' -- fmap :: Functor f => (a -> b) -> f a -> f b -- IO is a Functor, so we can use this to apply a function over the result useFmap :: String -> IO String useFmap str = fmap maybeUseG $ f str where maybeUseG :: String -> String maybeUseG s = fromMaybe s $ g s -- <$> is an operator alias for fmap useInlineFmap :: String -> IO String useInlineFmap str = maybeUseG <$> f str where maybeUseG :: String -> String maybeUseG s = fromMaybe s $ g s -- (<&>) = flip (<$>), which is often handy if you want to use a -- lambda for the function argument useBackwardFmap :: String -> IO String useBackwardFmap str = f str <&> \s -> fromMaybe s $ g s