Reputation: 28470
I came across this answer, where the claim that
A
Functor
instance is unique
left me a bit puzzled.
Ok, I think []
can be a Functor
only in 1 way, but (,)
can surely be made a Functor
in 2 symmetric ways.
And then I thought about the condition that must exist between Functor
and Applicative
, which is that fmap == (<*>) . pure
, and how that constraint is held true for lists: lists can implement Functor
in only 1 way, but Applicative
in 2 different ways
(differing in both (<*>)
and pure
).
So I thought: should I look at fmap == (<*>) . pure
as 1 equation in 3 unknowns, in which I can pick 2 and the third is determined?
And so here's the question: is there a datatype that can implement Functor
in 2 ways, and Applicative
also in 2 ways, but these latter two share either the same pure
or the same <*>
?
If not, is there a proof that?
Upvotes: 1
Views: 72
Reputation: 2149
See Koterpillar's answer for the Functor
part: (,)
cannot have a Functor
instance, but (,) a
can (and there is only one because lawful Functor
instances are unique by parametricity).
Any Applicative
functor gives rise to a Backwards
Applicative
with the same pure
(up to newtype
constructors) and whose (<*>)
sequences effects in the other direction, so if the Applicative
you started with comes from a non-commutative monad (such as []
or IO
or Writer m
for a non-commutative Monoid m
) then you get two different (<*>)
s.
> (,) <$> [1,2] <*> [3,4]
[(1,3),(1,4),(2,3),(2,4)]
> (,) <$> Backwards [1,2] <*> Backwards [3,4]
Backwards [(1,3),(2,3),(1,4),(2,4)]
Upvotes: 6
Reputation: 8173
Functor instances are unique, so the rest of the question is moot.
but
(,)
can surely be made aFunctor
in 2 simmetric[sic] ways.
The kind of (,)
is * -> * -> *
so it can't be a Functor without a clarification. In Haskell you can only fix the first type argument so (,) a
is a Functor for any a
(in a unique way).
If we had a newtype swapping the type arguments of (,)
then that would have a unique instance of Functor for any b
.
Upvotes: 7