instance (Semigroup a) => Applicative (These a) where
pure = That
This a <*> _ = This a
That _ <*> This b = This b
That f <*> That x = That (f x)
That f <*> These b x = These b (f x)
These a _ <*> This b = This (a <> b)
These a f <*> That x = These a (f x)
These a f <*> These b x = These (a <> b) (f x)

When one of the These is a This, the result is always This. However, there appears to be an assymetry when one of the These is a These constructor. The information from the These constructor is either preserved in the result or discarded, depending on which one is the argument.

This a <*> _ = This a
These a _ <*> This b = This (a <> b)

Testing this in ghci:

ghci> This "a" <*> These "b" True
This "a"
ghci> These "a" not <*> This "b"
This "ab"

What would the consequence be if we added a case like

This a <*> These b _ = This (a <> b)

to the Applicative instance? Would this break the Applicative laws?

Adding the case This a <*> These b _ = This (a <> b) to the Applicative instance of These would not break the Applicative laws.

The Applicative laws state that the pure function should behave as an identity under (<*>) and that (<*>) should be associative. Letâ€™s analyze these laws with the newly added case:

Identity Law: pure id <*> v = v

When v is This x, the result would be This x since This x is always returned when This is the first argument in the existing implementation.

When v is That y, These y z, or These y z, the result would be the same as before since the existing cases already handle these scenarios correctly.

Hence, the identity law would still hold.

Associative Law: u <*> (v <*> w) = (pure (.) <*> u <*> v) <*> w

When u is This x, v is This y, and w is This z, the result would be This (x <> (y <> z)) in both cases, since (x <> (y <> z)) is the same as ((x <> y) <> z).

When u is This x, v is This y, and w is That z or These z w, the result would be This (x <> y) in both cases, since (x <> y) is the same as ((x <> y) <> z).

This is consistent with the existing behavior of the other cases, so the associative law would still hold.

Therefore, adding the case This a <*> These b _ = This (a <> b) would not break the Applicative laws.