4

I'm new to this, and I may be missing something important. I've read part one of Category Theory for Programmers, but the most abstract math I did in university was Group Theory so I'm having to read very slowly.

I would ultimately like to understand the theory to ground my use of the techniques, so whenever I feel like I've made some progress I return to the fantasy-land spec to test myself. This time I felt like I knew where to start: I started with Functor.

From the fantasy-land spec:

Functor

  1. u.map(a => a) is equivalent to u (identity)
  2. u.map(x => f(g(x))) is equivalent to u.map(g).map(f) (composition)

map method

map :: Functor f => f a ~> (a -> b) -> f b 

A value which has a Functor must provide a map method. The map method takes one argument:

u.map(f) 
  1. f must be a function,

    i. If f is not a function, the behaviour of map is unspecified.

    ii.f can return any value.

    iii. No parts of f's return value should be checked.

  2. map must return a value of the same Functor

I don't understand the phrase "a value which has a functor".

What does it mean for a value to "have a functor"? I don't think "is a functor" or "belongs to a functor" would make any more sense here.

What is the documentation trying to say about u?


My understanding is that a functor is a mapping between categories (or in this case from a category to itself). We are working in the category of types, in which objects are types and morphisms are families of functions that take a type to another type, or a type to itself.

As far as I can tell, a functor maps a to Functor a. It has some kind of constructor like,

Functor :: a -> F a

and a map function like,

map :: Functor f => (a -> b) -> f a -> f b

The a refers to any type, and the family of functions (a -> b) refers to all morphisms pointing from any particular type a to any other particular type b. So it doesn't even really make sense to me to distinguish between values which do or do not "have a functor" because if at least one functor exists, then it exists "for" every type... so every value can be mapped by a function that belongs to a morphism between two types that has been lifted by a functor. What I mean is: please show me an example of a value which "does not have a functor".

The functor is the mapping; it isn't the type F a, and it isn't values of the type F a. So in the docs, the value u is not a functor, and I don't think it "has a" functor... it is a value of type F a.

Ziggy
  • 21,845
  • 28
  • 75
  • 104
  • taking your own definitions, a value which has a mapping between categories – Keith Nicholas Nov 24 '17 at 01:23
  • 1
    I'm voting to close this question as off-topic because it is not (yet) a programming question. – Raymond Chen Nov 24 '17 at 02:00
  • I acknowledge that this is abstract, but I hesitate to agree that this _is no_ a programming question. If the question was instead "what does it mean for a value to have a method" or "what does it mean for a value to have a type" would that be a programming question? – Ziggy Nov 24 '17 at 16:21
  • @RaymondChen although, on rereading my question, it does feel like it belongs in a discussion somewhere. Like, the only person equiped to answer this is the person who wrote the docs... so maybe vote to close! – Ziggy Nov 24 '17 at 18:12

1 Answers1

1

As you say, a functor in programming is a mapping between types, but JavaScript has not types, so you have to imagine them. Here, imagine that the function f goes from type a to type b. The value u is the result of some functor F acting on a. The result of u.map(f) is of the type F b, so you have a mapping from F a (that's the type of u) to F b. Here, map is treated as a method of u.

That's as close as you can get to a functor in JavaScript. (It doesn't help that the same letter f is alternatively used for the function and the functor in the documentation.)

Bartosz Milewski
  • 11,012
  • 5
  • 36
  • 45
  • Bartosz Milewski! Thank you for your writing/videos! The structure of the category of types is preserved by the functor, so if there are arrows from `a` to any other type, there will be arrows from `F a` in the same manner. If there is some `a -> b` then there is also `F a -> F b` and so on. We know this once we prove there exists a functor which maps `a` to `F a`. I feel like the docs would be more clear if they said "Given a type `F a`, there exists a functor that maps `a` to `F a` if and only if instances of `F a` implement a method `map` with the following properties:" Or something... – Ziggy Nov 24 '17 at 18:24