Given an operation (??)
such that
(a ?? b) ?? c = a ?? (b ?? c)
(that is to say (??)
is associative)
must it be the case that
liftA2 (??) (liftA2 (??) a b) c = liftA2 (??) a (liftA2 (??) b c)
(that is to say that liftA2 (??)
is associative)
If we would prefere we can rewrite this as:
fmap (??) (fmap (??) a <*> b) <*> c = fmap (??) a <*> (fmap (??) b <*> c)
I spent a little while staring at the applicative laws but I couldn't come up with a proof that this would be the case. So I set out to disprove it. All the out-of-the-box applicatives (Maybe
, []
, Either
, etc.) that I have tried, follow the law, so I thought I would create my own.
My best idea was to make a vacuous applicative with an extra piece of information attached.
data Vacuous a = Vac Alg
Where Alg
would be some algebra I would define at my own convenience later as to make the property fail but the applicative laws succeed.
Now we define our instances as such:
instance Functor Vacuous where
fmap f = id
instance Applicative Vacuous where
pure x = Vac i
liftA2 f (Vac a) (Vac b) = Vac (comb a b)
(Vac a) <*> (Vac b) = Vac (comb a b)
Where i
is some element of Alg
to be determined and comb
is a binary combinator on Alg
also to be determined. There is not really another way we can go about defining this.
If we want to fulfill the Identiy law this forces i
to be an idenity over comb
. We then get Homomorphism and Interchange for free. But now Composition forces comb
to be associative over Alg
((pure (.) <*> Vac u) <*> Vac v) <*> Vac w = Vac u <*> (Vac v <*> Vac w)
((Vac i <*> Vac u) <*> Vac v) <*> Vac w = Vac u <*> (Vac v <*> Vac w)
(Vac u <*> Vac v) <*> Vac w = Vac u <*> (Vac v <*> Vac w)
(Vac (comb u v)) <*> Vac w = Vac u <*> (Vac (comb v w))
Vac (comb (comb u v) w) = Vac (comb u (comb v w))
comb (comb u v) w = comb u (comb v w)
Forcing us to satisfy the property.
Is there a counter example? If not how can we prove this property?
base
'sinstance (Applicative f, Semigroup a) => Semigroup (Ap f a)
relies on this property being true. – Silverts