Enlico
Enlico

Reputation: 28470

Is there a data type with two Functor instances and two Applicative instances, the latter with either 1 pure and 2 ap or vice-versa?

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

Answers (2)

Na&#239;m Favier
Na&#239;m Favier

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

Koterpillar
Koterpillar

Reputation: 8173

Functor instances are unique, so the rest of the question is moot.

but (,) can surely be made a Functor 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

Related Questions