functionhaskellfunctional-programmingdot-operator

Combining (a -> Maybe a) and (a -> a) functions


I have two functions:

f :: a -> Maybe a
g :: a -> a

I want to create such function:

h :: a -> Maybe a

h x
| isJust(f x) = Just (g $ fromJust(f x))
| otherwise   = Nothing

How can I do it in more elegant way?


Solution

  • Since you've tagged this question with :

    h :: a -> Maybe a
    h = fmap g . f
    

    For an explanation:

    f            ::                          a -> Maybe a
    g            ::        a ->       a
    fmap g       ::  Maybe a -> Maybe a
    (.)          :: (Maybe a -> Maybe a) -> (a -> Maybe a) -> (a -> Maybe a)
    (.) (fmap g) ::                         (a -> Maybe a) -> (a -> Maybe a)
    fmap g . f   ::                                           (a -> Maybe a)
    h            ::                                            a -> Maybe a
    

    Note that (.)'s and fmap g's types are actually more general:

    (.) :: (b -> c) -> (a -> b) -> (a -> c)
    -- b in this case is Maybe a
    -- c in this case is Maybe a
    
    fmap g :: Functor f => f a -> f a
    -- f in this case is Maybe
    

    However, you could also pattern match on the result of f:

    h x = 
      case f x of
        Just k -> Just (g k)
        _      -> Nothing
    

    Note that your original example wouldn't even compile, since g's return type isn't correct.