I want a shorter way to write this block of code as this is going to be used in multiple places in a project I am working on. Is there a library I can use which would have a function for my specific need?
case mbData1, mbData2 of
(Just data1, Just data2) -> Just $ mergeData data1 data2
(Nothing, Just data2) -> Just data2
(Just data1, Nothing) -> Just data1
(Nothing, Nothing) -> Nothing
CodePudding user response:
First, note that your expression only makes sense if mergeData x y
has the same type as x
and y
each have, i.e. if its type is
mergeData :: X -> X -> X
for some concrete type X
.
Given that, we can rely on Maybe's Applicative and Alternative instances:
mergeTwoMaybeDatas :: Maybe X -> Maybe X -> Maybe X
mergeTwoMaybeDatas a b = liftA2 mergeData a b <|> a <|> b
If you want to reuse this pattern many times but for different functions, and you think this is not clear, you could define a function parameterizing over mergeData
.
But wait, maybe we can do something even simpler! If your mergeData
function is associative (i.e., mergeData x (mergeData y z) = mergeData (mergeData x y) z
), then your X type is a Semigroup, with mergeData
as its combine operation. In that case, consider defining the Semigroup instance. Then you could use the tools designed for Semigroups to handle this even more simply.
data X = ...
instance Semigroup X where
(<>) = mergeData
mergeTwoMaybeDatas :: Maybe X -> Maybe X -> Maybe X
mergeTwoMaybeDatas = (<>)
Amazing: if you give X its Semigroup instance, you don't even have to implement mergeTwoMaybeDatas
at all - it's just how (<>)
already behaves for a Semigroup lifted into Maybe.
I encourage giving your types instances of all the typeclasses they can reasonably support: you will find many generic tools like this then work on them "for free". Having a Semigroup instance will likely help out for some of your other uses of this X type as well.
CodePudding user response:
You're looking for the salign
function from the semialign
package. Create a Semigroup
instance for your type, with (<>) = mergeData
(or inline its definition and just always call it this way), and then
just call salign mbData1 mbData2
.