Contravariant functors are actually really nice. The classic example from maths is the spectrum (Spec) of a ring R. As a functor, Spec(R) = the set of prime ideals of R. An example anyone can understand: all the multiples of prime numbers p Z, in the integers Z. Let R -> S is a ring homomorphism, then there is an induced map Spec(S) -> Spec(R). Spec establishes a connection between the category of rings and topologic…
While I know precisely what you are saying (have been learning scheme theory this summer), this is hardly an accessible example to pure math undergrads , let alone someone who's attempting to learn some functional programming, with no heavy experience with abstract algebra. First of all, why use Spec? Use ideals/varieties, it contains roughly the same data, while being way better to intuit. I'll put my money where my…
Contravariant Functors Are Weird
11–20 of 26 posts
Re: Contravariant Functors Are Weird
#12Earlier quoted context omitted.
While I know precisely what you are saying (have been learning scheme theory this summer), this is hardly an accessible example to pure math undergrads , let alone someone who's attempting to learn some functional programming, with no heavy experience with abstract algebra. First of all, why use Spec? Use ideals/varieties, it contains roughly the same data, while being way better to intuit. I'll put my money where my…
I have undergrad-level understanding of both abstract algebra and functional programming, and I have absolutely no idea how either your or the GP's example are connected to contravariant functors as understood through the lens of functional programming.
Suppose I have a function f : x -> y. x -> y is also a functor in y. If you have an x-> y but want x->z, you can use y->z and adjust your original function by post processing the output of f. However suppose you want w -> y but you still only have f. You need to post process with w->x. So f is covariant in y, contravariant in x. Things change in the opposite direction of the adaptor.
Perhaps serialisation is a useful example?
Perhaps contravariance becomes even more useful if you use it in some profunctor dimap where you have a producer and consumer and process, eg moving through a data structure and pre/post processing things.
Re: Contravariant Functors Are Weird
#13Some days I even think "hey functional programming looks fun, I should try it!"
Then I read articles like this and realize that ship has sailed...
I'll be sticking to my procedural code, now with a light sprinkling of functional-ish concepts.
Re: Contravariant Functors Are Weird
#14Earlier quoted context omitted.
I have undergrad-level understanding of both abstract algebra and functional programming, and I have absolutely no idea how either your or the GP's example are connected to contravariant functors as understood through the lens of functional programming.
Maybe a good example that ties both together is some sort of filter on a list? If you add more constraints (more processing) the list gets smaller. Suppose I have a function f : x -> y. x -> y is also a functor in y. If you have an x-> y but want x->z, you can use y->z and adjust your original function by post processing the output of f. However suppose you want w -> y but you still only have f. You need to post proc…
Did you mean pre-process?
Re: Contravariant Functors Are Weird
#15One thing I've never understood is polarity. To my understanding, positive types are defined in terms of their introduction rules and negative types are defined in terms of their elimination rules. However, don't types both have introduction and elimination rules, making them positive or negative based on how you choose to define them? Also, how does polarity (emphasis on introduction versus elimination rules) relate…
As an example, the function type `A -> B` is negative because the function introduction rule
G, x:A |- M : B ---------------- G |- lam x. M : A -> B
is a bijection: the inverse is
G |- N : A -> B ------------------- G , x:A |- N x : B
The beta and eta equations encode exactly the two properties of this being a bijection.
Positive types, like sums/alternatives/coproducts have their elimination rule as their reversible rule, i.e. "pattern matching". So the rule
G , x1 : A1 |- K1 : B G , x2 : A2 |- K2 : B --------------------- G , x : A1 + A1 |- case x of { in1 x1. K1 | n2 x2. K2 }
Has an inverse
G , x : A1 + A2 |- N : B --------------------------- G , x1 : A1 |- N[in1 x1/x] G , x2 : A2 |- N[in2 x2/x]
The reason people say the positive types are "defined in terms of their introduction rules" is that you say "here are all the ways to build a term of this type" (in1 and in2 for sums) and then the elimination rule is exactly "pattern match on all of those possibilities". There is a dual way to think of the negative types which is "here are all the ways to use a term of this type" and the introduction form is a "co-pattern match" where you say "inspect all of the ways I can be used and say what to do in each case".
If you know about category theory then the idea is that some types are defined by representing a functor C -> Set (positives) and others by representing a functor C^op -> Set (negatives).
Variance is I would say is an orthogonal concept, except that the only primitive contravariant type former in lambda calculus is function which is negative.
Re: Contravariant Functors Are Weird
#16However we can also treat (len : string -> int) as a contravariant functor by pre-composing instead of post-composing. Say we have a function (h : int -> Y), then we can form (k : string -> Y) by setting k(s) = k(len(s)). This could be useful if we only cared about whether a strings length were a multiple of 5, say.
Some of the above are lies: in order to call these functors in the mathematical sense (or the Haskell sense) you need to phrase things in just the right way. But I think it gets the idea across about how simple the difference between co- and contra- variance can be, with the example of replacing f(x) by g(f(x)) or by f(g(x)).
Re: Contravariant Functors Are Weird
#17I'm not a functional programmer, but I like reading about it to expand my horizon. Some days I even think "hey functional programming looks fun, I should try it!" Then I read articles like this and realize that ship has sailed... I'll be sticking to my procedural code, now with a light sprinkling of functional-ish concepts.
Re: Contravariant Functors Are Weird
#18I'm not a functional programmer, but I like reading about it to expand my horizon. Some days I even think "hey functional programming looks fun, I should try it!" Then I read articles like this and realize that ship has sailed... I'll be sticking to my procedural code, now with a light sprinkling of functional-ish concepts.
Honestly, concepts like functors are not that hard, they're way more intuitive than some of the OOP concepts when you get used to them a little bit.
I mean the Haskell wiki[1] is no use to a guy like me. Not a complaint, it's a reference after all. Wikipedia[2] isn't much better, which I do find slightly disappointing.
At least the Wikipedia article has some links to the concepts involved so should be doable to interpret the terse article after a bit of extra reading.
[1]: https://wiki.haskell.org/Functor
[2]: https://en.wikipedia.org/wiki/Functor_(functional_programmin...
Re: Contravariant Functors Are Weird
#19From concreteness, let's suppose we're talking about sets and functions between sets. (The same thing works in an arbitrary category.) Thus, if X and Y are sets, Hom(X, Y) denotes the set of functions (morphisms) from X to Y. Suppose you have a fixed function f: A -> B. You can compose it with functions into A or out of B.
If g: C -> A maps into A, then f o g (using "o" to denote composition) gives a function from C to B: that is, f o g: C -> A -> B. We started with a function from C to A and wound up with a function from C to B. So we actually have a function (functor) Hom(C, A) -> Hom(C, B), which is often denoted Hom(C, f). We say that Hom(C, -) is covariant, because it respects the direction of arrows in the second slot. (f went from A to B, and Hom(C, f) goes from Hom(C, A) to Hom(C, B).)
If h: B -> D maps out of B, then h o f gives a function from A to D: that is, h o f: A -> B -> D. So we actually have a function from Hom(B, D) -> Hom(A, D) which is often denoted Hom(f, D). We say that Hom(-, D) is contravarient, because it reverses the direction of arrows in the first slot. (f went from A to B, but Hom(f, D) goes from Hom(B, D) to Hom(A, D).)
g f h
C ---> A ---> B ---> D
Thus, Hom(-, -) is actually a bifunctor which is covariant in one variable and contravariant in the other. Contravariant functors can be regarded as covariant functors on the opposite category. What is happening with Hom is a prototype for many of the ways that "covariance" and "contravariance" occur in math; for example, covariant and contravariant tensors. (The vector dual space function Hom(-, K) [where K is the ground field] is contravariant.)One of the earliest descriptions of category theory (including variance) is in: Samuel Eilenberg and Saunders MacLane, "General Theory of Natural Equivalences". Transactions of the American Mathematical Society, Vol. 58, No. 2, (Sep., 1945), pp. 231-294
It's actually fairly readable. There have been many books and articles on category theory since then, and many specifically directed toward computer science (e.g. Michael Barr and Charles Wells, "Category Theory for Computer Science" - https://www.math.mcgill.ca/triples/Barr-Wells-ctcs.pdf).
Re: Contravariant Functors Are Weird
#20Earlier quoted context omitted.
Honestly, concepts like functors are not that hard, they're way more intuitive than some of the OOP concepts when you get used to them a little bit.
Yeah I guess it's mostly about not knowing Haskell syntax so the code samples don't really do much for me, and not knowing any category theory so that's no use either. I mean the Haskell wiki[1] is no use to a guy like me. Not a complaint, it's a reference after all. Wikipedia[2] isn't much better, which I do find slightly disappointing. At least the Wikipedia article has some links to the concepts involved so should…