Live data from Hacker News

Haskell is not category theory

pema.dev

11–20 of 54 posts

Re: Haskell is not category theory

#11

I'm confused by his argument that Haskell functors are only endofunctors because everything is Hask. I thought that even if everything is part of one category, if the input is a different category that is a subset of the one category and transformed to another category, even if a subset of the same category, it could still be a regular functor instead of an endofunctor. For example, lets say you had a function f(x) t…

I believe the heart of what you're asking is "why do we distinguish between codomain and range?" and relatedly why do we even need the concept of "surjectivity?" For example, the function f(x) = x + x could be thought of a non-surjective "endo-"function (endomorphism) `N -> N` (where N is the natural numbers) or it could be thought of as a surjective function from `N -> E` (where E is the even natural numbers). Why do we need the "looser" version of `N -> N` when we can do with the tighter bound `N -> E`?

As with many definitional things in pure mathematics, the answer is "there's no absolute iron-clad reason why you can't think of things that way, but there are a variety of reasons both mechanistic and motivated by intuition why you might not want to do that."

To motivate it via intuition, let me start with another example. Take the function that maps every natural number k to the function f(x) = x + k (so it's a function whose codomain is `(N -> N)` or also expressed as `N^N`, allowing again for the fact that N^N is again "too loose" since we only care about functions of the form f(x) = x + k). Now someone could come along and say "well, f(x) = x + k" can be simply identified with just k so really the function we have is the identity function on `N -> N`, but I think most people would object and say that `k` is not the same thing as `f(x) = x + k`. The former can be thought of as an encoding of the latter, but it's not the same thing. So saying that the codomain of our function is N^N is in some sense more accurate than N and instead we can say that there's a way of embedding a subset of N^N into N via encoding f(x) = x + k as just k.

The crucial thing here is that deciding whether we are dealing with an artificial encoding of something, or the real thing itself is what lets us distinguish between saying that the function's codomain is N vs N^N, and in some sense the former feels "wrong" even though it's a "tighter bound."

Let's develop that intuition a little bit further. Imagine you have a function that takes a rational number and maps it to the largest integer smaller than it (that is the floor function). You could think of this function in one of at least four ways:

1. Q -> Q: A function that maps a rational number back to a rational number 2. Q -> Z: A function that maps a rational number to an integer 3. Z -> Z: Because rational numbers are countable, every rational number is "just" the indexed form of an integer, so "really" what we have is a function from Z -> Z 4. N -> N: Well by the same logic, every function on integers is just a function on natural numbers!

I think the last two probably feel the most "unnatural" for folks, and most representative of the problem of "representation vs what an object 'really' is" I talked about earlier. But the first two have what is basically the same choice, just in a context where the answer isn't as clear. Do you think the integer 2 really is just the same number as the rational number "2 / 1?" Or do you think that they are different from each other and an encoding process is necessary to move from one to the other? In some cases it's useful to say "yes every integer is exactly a rational number" and in that case we can say that Q -> Q reflects this intuition best. In other cases it might be more useful to say "no an integer is not a rational number, but there is a canonical way of identifying every integer with a certain rational number" and in that case we can say that Q -> Z reflects that intuition.

So your choice of codomain reflects what you think an object "really is" as opposed to just being an encoding. In this case we say that choosing Hask as the codomain (or "target") of our functor, hence making it an endofunctor, is a choice that reflects an intuition that the result of mapping using a Haskell functor is really just another type, not some other object that can be thought of as a type.

From this intuition there flows a variety of practical, mechanistic ramifications. Almost always when talking about mappings we are concerned about how they affect the structure of the source and target. When we say the codomain is the same as the domain, we also almost always mean that structurally they are the same and this considerably simplifies the analysis we need to do later, because we can reuse a lot of the same machinery in the domain and codomain. If you say that the codomain and domain are not the same, then all of a sudden you have to concern yourself with the structure of the codomain and domain and prove that all the equivalences and isomorphisms you want to hold and preserve the properties you care about do actually exist and do actually preserve everything you want preserved and it's just a lot more annoying.

So at a mechanistic level, what we gain from saying that "Haskell functors are only endofunctors because everything is Hask" is that we know we never map into something that has more structure than Hask; it always has the same structure. So we don't have to concern ourselves with a bunch of exploration into what happens if we map into a category with more structure than Hask.

Re: Haskell is not category theory

#12

I'm confused by his argument that Haskell functors are only endofunctors because everything is Hask. I thought that even if everything is part of one category, if the input is a different category that is a subset of the one category and transformed to another category, even if a subset of the same category, it could still be a regular functor instead of an endofunctor. For example, lets say you had a function f(x) t…

You could probably try to talk about functors between subcategories by using classes, though I think there's no way to define a functor from one class to another in Haskell. Slightly more annoying is the fact that Haskell has no real product types and instead does more currying than an Indian takeaway. This makes various constructions in Category theory a bit more annoying than they need to be. If you ever wondered w…

Haskell isn't the functor police! It's on you to define good functors, proving them so would be a totally different endeavour and far more difficult.

I would like to understand better the issue with product types though. What do you want to do that you can't currently.

By the way, most of my knowledge about the connection between Haskell and Category Theory comes from here: https://bartoszmilewski.com/2014/10/28/category-theory-for-p...

Re: Haskell is not category theory

#13
From my late-beginner Coq student perspective, I'm amused to think that the loop detection in Haskell (which allows you to distinguish divergence from a specific instance of a type) might have made Haskell less sound from a type theory perspective, because it is in some way intervening in the calculation to add or detect distinctions that would otherwise not be a part of the underlying theory!

Well, maybe that's not the best way to put it: but the example of using the > detection to distinguish a loop from a concrete instance is something that Haskell added presumably for users' convenience; if it didn't have that feature, you would not, in fact, be able to distinguish the infinite loop from a specific value in finite time, except by manually examining the implementation!

Re: Haskell is not category theory

#14
And you definitely don't need to learn category theory or know anything about it to start writing programs in Haskell or to maintain and build large Haskell applications.

A lot of category theory is fun to learn and knowing it will help you in many ways but it is not a necessary requirement. I mention this because a lot of people seem to think it is.

Definitely a nice article for the math-oriented/curious/etc! It's neat seeing what Haskell isn't in order to understand better what it is.

Re: Haskell is not category theory

#15

> If you are looking to learn the language, I recommend Learn You A Haskell. I definitely don't recommend this. While cute, Learn You A Haskell is lacking a lot of pragmatic advice about how to write software in haskell. It's good for getting you up to the FAM trio of type classes but leaves out a lot of practical advice around things like navigating base (what to use and ditch from it), the available community libra…

Feels worth mentioning that Learn You A Haskell is about 1/3 the length of the book you mentioned.

I agree that it won't teach you all you need to know to be really proficient with the language, and also wish it didn't omit monad transformers in particular. I still like that it's an easy read, and that I could hand it to someone with pretty much zero knowledge of FP. I used sections of it as a first resource, and then learned the rest by reading documentation, which is how I usually deal with new languages.

I haven't read the book you suggested, so can't comment on the content, but seeing that the first chapter is on lambda calculus makes me a bit skeptical. Perhaps you can tell me, is the book similarly beginner friendly?

Re: Haskell is not category theory

#16
post #6
post #5

Earlier quoted context omitted.

I mostly agree with your recommendation against Learn You A Haskell. However I would suggest people have a look at https://en.wikibooks.org/wiki/Haskell 'Haskell Programming From First Principles' is a bit too fan-boyish.

I thought fanboyism was one of the first principles.

The only language I've seen where developers are less fanboys of it than Haskell is C++.

Try asking one what is wrong with the language.

Re: Haskell is not category theory

#17

I'm confused by his argument that Haskell functors are only endofunctors because everything is Hask. I thought that even if everything is part of one category, if the input is a different category that is a subset of the one category and transformed to another category, even if a subset of the same category, it could still be a regular functor instead of an endofunctor. For example, lets say you had a function f(x) t…

I believe the heart of what you're asking is "why do we distinguish between codomain and range?" and relatedly why do we even need the concept of "surjectivity?" For example, the function f(x) = x + x could be thought of a non-surjective "endo-"function (endomorphism) `N -> N` (where N is the natural numbers) or it could be thought of as a surjective function from `N -> E` (where E is the even natural numbers). Why d…

Thank you for the incredibly thorough writeup. I've read it once but I can tell I'm going to need a few more passes at least before I fully grasp everything because there is a TON of nuance (which does not surprise me I know just enough to realize Category theory by nature is full of nuance).

A question for you, do you think there would be any value in a programming language that DID include the need to concern itself with the structural differences between two categories or are we getting into issues like too much boilerplate to encode anything useful territory and similar?

Re: Haskell is not category theory

#18
post #12

Earlier quoted context omitted.

You could probably try to talk about functors between subcategories by using classes, though I think there's no way to define a functor from one class to another in Haskell. Slightly more annoying is the fact that Haskell has no real product types and instead does more currying than an Indian takeaway. This makes various constructions in Category theory a bit more annoying than they need to be. If you ever wondered w…

Haskell isn't the functor police! It's on you to define good functors, proving them so would be a totally different endeavour and far more difficult. I would like to understand better the issue with product types though. What do you want to do that you can't currently. By the way, most of my knowledge about the connection between Haskell and Category Theory comes from here: https://bartoszmilewski.com/2014/10/28/cate…

What is an example of category-theory functor in Haskell, that isn't just an endofunctor?

A functor F from C to D is a mapping that associates each object X in C to an object F(X) in D.

In Haskell, C and D are both the same (Hask types), hence endofunctor (functor into self).

In general a functor could be something like `prime_factorizaton:: Int -> [(Prime Int, Mulitplicity Int)]`, with morphisms being things like the operation

  a => square :: a -> a
  square (n::Integer) = n^2
  square (factorization::[(Prime Int, Mulitplicity Int)]) = map (\(a,b) -> (a, 2*b)))

prime_factorizaton (square) x === square (prime_factorization(x))

Re: Haskell is not category theory

#19

And you definitely don't need to learn category theory or know anything about it to start writing programs in Haskell or to maintain and build large Haskell applications. A lot of category theory is fun to learn and knowing it will help you in many ways but it is not a necessary requirement. I mention this because a lot of people seem to think it is. Definitely a nice article for the math-oriented/curious/etc! It's n…

> A lot of category theory is fun to learn and knowing it will help you in many ways

I agree with your statement except that part.

W.r.t coding, learning functional programing will help you in many ways. Learning category theory will just allow you to say "ah I've seen that concept before" - but it won't really help much.

Re: Haskell is not category theory

#20

> If you are looking to learn the language, I recommend Learn You A Haskell. I definitely don't recommend this. While cute, Learn You A Haskell is lacking a lot of pragmatic advice about how to write software in haskell. It's good for getting you up to the FAM trio of type classes but leaves out a lot of practical advice around things like navigating base (what to use and ditch from it), the available community libra…

You can read LYAH and go build a project. You may have to also read Haddocks but LYAH equips you to understand them and okay type tetris.

You can definitely read LYAH and read the scotty and postgresql-simple docs and be on your way. You may also want to reference the GHC manual.

Post reply on HN