Why is `pure` only required for Applicative and not already for Functor?

Reading this Wikibook about Haskell and Category Theory basics, I learn about Functors:

A functor is essentially a transformation between categories, so given categories C and D, a functor F : C -> D

maps any object A in C to F(A), in D.

maps morphisms f : A -> B in C to F(f) : F(A) -> F(B) in D.

... which sounds all nice. Later an example is provided:

Let's have a sample instance, too:

instance Functor Maybe where
  fmap f (Just x) = Just (f x)
  fmap _ Nothing  = Nothing

Here's the key part: the type constructor Maybe takes any type T to a new type, Maybe T. Also, fmap restricted to Maybe types takes a function a -> b to a function Maybe a -> Maybe b. But that's it! We've defined two parts, something that takes objects in Hask to objects in another category (that of Maybe types and functions defined on Maybe types), and something that takes morphisms in Hask to morphisms in this category. So Maybe is a functor.

I understand how the definition of fmap is key. I am confused about how the "type constructor Maybe" provides the first part. I would have rather expected something like pure .

If I get it right, Maybe rather maps C to D . (Thus being a morphism on category level, which might be a requirement for a Functor)

I guess you could rephrase my question like this: Is there a Functor that does not have an obvious implementation of pure ?


I think you're getting confused between types and values. Here's the definition of a functor:

Let C and D be categories. A functor F from C to D is a mapping that:

  • associates to each object X ∈ C an object F(X) ∈ D.
  • associates to each morphism f : X → Y ∈ C a morphism F(f) : F(X) → F(Y) ∈ D such that the following conditions hold:

  • F(id : X → X) = id : F(X) → F(X) for every object X ∈ C.
  • F(g ∘ f) = F(g) ∘ F(f) for all morphisms f : X → Y and g : Y → Z.
  • A category consists of objects and morphisms between objects.

    All code in Haskell is a part of Hask, the Haskell category. In Hask:

  • Types are objects.
  • Functions are morphisms between types.
  • Hence, all Functor instances in Haskell are functors from Hask to Hask (ie they are endofunctors).

    To put it more rigorously, for all instances of Functor in Haskell:

  • C = Hask .
  • D = Hask .
  • Now, each functor F is a mapping that associates to each object X ∈ C an object F(X) ∈ D.

  • Note that X and F(X) are objects of C and D respectively.
  • Since both C and D are Hask, both X and F(X) are types and not values.
  • Thus, F : Type → Type or in Haskell f : * -> * .
  • Indeed, this is precisely how the Functor type class is defined in Haskell:

    class Functor (f : * -> *) where
        fmap :: (x -> y) -> (f x -> f y)
    

    Here, fmap is the second part of the functor. It's a function from values to values. However, the Functor itself is a type constructor (ie a mapping from types to types). This is the reason Maybe is a functor and [] is a functor but Maybe Int and [Int] are not functors.

    Note that pure does not form the first part of the functor definition because it's a mapping from an instance of X to an instance of F(X) (ie it's a function from values to values). However, we need a mapping from X to F(X) (ie a mapping from types to types).


    If I get it right, Maybe rather maps C to D . (Thus being a morphism on category level, which might be a requirement for a Functor)

    Not really, as C and D there are categories, and not Haskell types. A Functor (that is, an instance of the type class, as opposed to a functor in general) is a mapping from the Hask category (the category of Haskell types and functions) to Hask itself; that is, C and D are both Hask in that case. The Wikibook chapter mentions that in the section Functors on Hask. In your example, the Maybe type constructor provides the first part of the mapping by taking some type a (an object in Hask ) to the type Maybe a (another object in Hask ).

    I guess you could rephrase my question like this: Is there a Functor that does not have an obvious implementation of pure ?

    One example is the pair Functor , (,) a . fmap is easy to write -- f (x, y) -> (x, fy) -- but pure and (<*>) require a Monoid constraint on a , as there would be no way of dealing with the extra a values otherwise. For more discussion and other examples, see Good examples of Not a Functor/Functor/Applicative/Monad?


    I'd say that Applicative instance kind of becomes a stretch for Either (which I'd be perfectly fine with just having an instance for Bifunctor , but on the other hand using it as a Monad is convenient), and would (IMHO) be inappropriate for something like:

    data ABC a = A a | B a | C a
    

    Where all of A,B,C are "equally OK". Since there's no obvious choice for which should be used for pure , it shouldn't be provided at all. Having fmap is still perfectly fine, though.

    链接地址: http://www.djcxy.com/p/43314.html

    上一篇: Haskell:monoidal类别中的态射构成

    下一篇: 为什么`pure`只适用于Applicative而不是Functor?