If we could do it all over again, could pure be a method of the Functor typeclass?

Heh, yeah, I guess so!

I agree with nearly everything everyone said, but: The Pure type class should be in parallel with the Apply type class, Apply should not be a superclass of Pure. One reason is, again, van-Laarhoven encoding of optics:

  • Functor gives you lenses (exactly one focus)
  • Applicative gives you traversals (any number of foci)
  • Pure gives you affine traversals (0 or 1 focus)
  • Apply gives you traversals with 1 or more foci

Each is useful on their own, and different. They form a true diamond.

6 Likes

Ed’s reflections on class Pointed also probably apply here.

2 Likes

Adding pure into Functor would restrict the functionality of the typeclass for types that have a “conditional” Applicative instance, such as:

instance Monoid a => Applicative (Const a) where ...
instance Monoid a => Applicative ((,) a) where ...

Both of these need mempty to create pure values, but this is not required by their Functor instances for fmap.

Expanding on the semigroupoids comment by @Ambrose: For intuition on why pure should not be in a superclass of the class that provides <*>, you might want to consider a rather similar situation with Semigroups (which provide the squashing operation <>, similar to <*>) and Monoids (which add the unit-creating mempty, similar to pure). The actual connection is exemplified by Ap.

1 Like