Reputation: 698
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?
Upvotes: 3
Views: 186
Reputation: 12715
Having
fmap2 :: (Functor g, Functor f) => (a -> b) -> g (f a) -> g (f b)
fmap2 = fmap . fmap
here is a funny way:
h :: a -> Maybe a
h = fmap2 g f
fmap2 g f ~> fmap (fmap g) f ~> fmap g . f ~> \x -> fmap g (f x)
The Functor ((->) r)
instance is used here: fmap
can be used instead of (.)
.
Upvotes: 5
Reputation: 48654
Why not simply this:
h :: a -> Maybe a
h x = fmap g (f x)
Or the operator version:
h :: a -> Maybe a
h x = g <$> f x
Upvotes: 4
Reputation: 105886
Since you've tagged this question with dot-operator:
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.
Upvotes: 12