Consider these two functions in Haskell:
replace_snd :: b -> Maybe (a, b) -> Maybe (a, b)
replace_snd y' (Just (x, y)) = Just (x, y')
replace_snd _ Nothing = Nothing
inject_snd :: Maybe b -> (a, b) -> Maybe (a, b)
inject_snd (Just b') (a, b) = Just (a, b')
inject_snd Nothing _ = Nothing
replace_snd
replaces the second element of a pair, or returns Nothing if there is no pair:
> replace_snd 30 (Just (1, 2))
Just (1,30)
> replace_snd 30 Nothing
Nothing
inject_snd
replaces the second element, or returns Nothing if there is no replacement:
> inject_snd (Just 30) (1, 2)
Just (1,30)
> inject_snd Nothing (1, 2)
Nothing
Also consider their symmetric counterparts replace_fst
, inject_fst
that act on the first element of a pair:
replace_fst :: a -> Maybe (a, b) -> Maybe (a, b)
replace_fst x' (Just (x, y)) = Just (x', y)
replace_fst _ Nothing = Nothing
inject_fst :: Maybe a -> (a, b) -> Maybe (a, b)
inject_fst (Just a') (a, b) = Just (a', b)
inject_fst Nothing _ = Nothing
My question is this: Which of these four functions can be written more compactly using built-in functions such as monadic operators? And how?
For example, I've realized that inject_snd
is just (mapM . const)
, because Maybe
is a Monad
and ((,) a)
is a Traversable
:
> (mapM . const) (Just 30) (1, 2)
Just (1,30)
> (mapM . const) Nothing (1, 2)
Nothing
Are there similarly compact equivalents for the other three functions?
Alternatively
fmap . fmap . const
, which doesn't require theArrow
import... but I dislike the(a,)
functor, and this wouldn't extend toreplaceFst
. WithArrow
however, it's just as easy:The
inject
s are a bit more awkward, but can still readily be done with an application-operator section:Again, you could replace
second
withfmap
, but please don't.This can also be written
Of course, if you're ok with flipping the signature around, then the
flip
is unnecessary: