I'm looking at the These
datatype from the these package, in particular at its Applicative
instance:
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)
If one of the These
is a This
, the result is always This
. However, there seems to be a certain assymetry.
Here, if the second component is a These
constructor, its information is completely discarded:
This a <*> _ = This a
here the first component is a These
constructor, but the a
part is preserved in the result.
These a _ <*> This b = This (a <> b)
Testing it in ghci:
ghci> This "a" <*> These "b" True
This "a"
ghci> These "a" not <*> This "b"
This "ab"
But what if we added a case at the beginning like
This a <*> These b _ = This (a <> b)
Would that break the Applicative
laws?
Applicative
instance has to be biased in this way to be compatible with theMonad
one, and that a different, more symmetrical, instance should be possible, along the lines of whatValidation
is forEither
. (I haven't thought it through yet, though.) – Involuntary, and there's no way to call
g` here, so the only sensible result isThis a
. I guess this forces the bias mentioned by duplode. Perhaps we could also have a non-monad variant ofThese
which is more symmetrical. Anyway, you could try to run QuickCheck on the applicative laws just for fun. – Phraseology