577 karma · joined May 5, 2021
I would argue that type theory does a better job at this than set theory. With set theory, you need to believe in two separate things: (1) the language of first-order logic (or some other logic) with its inference rules, (2) the set theory axioms. With type theory, there is only the language of lambda terms. And the rules for type theory are straightforward and intuitive for programmers, e.g., you can only call a function on an argument if the function's domain matches the type of the argument. Contrast that with set theory, where you have highly counterintuitive and seemingly arbitrary axioms like the axiom of separation.
Martin-Löf type theory (and, therefore, homotopy type theory) is like an idealized programming language that is capable of expressing both programs and proofs, such that you can prove your code correct in the same language. Hacker News is a mostly technical community that often likes to geek out on programming languages.
Homotopy type theory is an especially cool flavor of type theory that finally gives a satisfying answer to the question of when two types should be considered propositionally equal.
That's not what constructive logic means.
You might want to consider adopting a more modern programming style for the benefit of your coworkers (and possibly yourself). Mutability all over the place is a nightmare, speaking as someone who currently has to work in a large codebase written like that. It's hard to predict what value a variable is going to have at any particular point in your code, since instead of only having to check where the variable is defined, you have to audit all the code between the definition and the use. For the same reason, it's hard to guarantee that your invariants are maintained, since there is a much larger surface area to check.
What's wrong with this? I need a way to describe techniques that make it easier to...well I don't even know another way to say it. Maybe I'm biased by my experience in formal verification, a field in which it's expected that you can formally study a program's behavior.
The main difference to me is that, with inductive reasoning (in the philosophical sense), you converge on a general principle but it might be wrong—it is only probable. Mathematical induction is the tool needed to close the gap—to turn a hypothesis which could be wrong into a bulletproof mathematical theorem. Of course, if your induction hypothesis didn't turn out to be right, you won't be able to complete the proof.
I use the Coq theorem prover to write induction proofs all the time, and often you have to try out different induction hypotheses until you get one that finally works. The process my brain goes through to come up with these induction hypotheses feels like "inductive reasoning" in the philosophical sense as I understand it.
JavaScript has Int64?
Yes, I totally support this! Coming from languages like Haskell, most languages look so unnecessarily noisy to me. Cut the fat!
> Anyone who proposes a way to minimize Lisp parentheses, who hasn't introduced a symbol for missing outline levels, is just pulling out chunks and hasn't used their system to write thousands of lines of code.
What are outline levels? I tried Googling it but didn't find anything.
> C syntax is ground glass in my eyes.
Is that a good thing? I'm not sure what you mean by it.
That said, I'm all for anything that results in more appreciation for mathematical rigor in programming. It's like puling teeth trying to get colleagues to use tools/languages that help with reasoning about code (even just a good type system), and for a lot of programmers math seems to be an unapproachable alien language.
One thing I'd like to change about the software industry is the perception that formal verification is too hard to do in practice because you can't even write down a complete specification for the program. The misconception there is that the all of the program's behavior needs to be specified in order for formal verification to be useful. Why can't gradual formal verification be a thing?
People who already know FP would be fine. Newcomers would be the ones to suffer. We already have a large number of tutorials, blogs, books, etc. using the existing terminology. For a programmer new to FP to tap into that they would need to learn both the "friendlier" (whatever that means) terms as well as how they map to the math terms.
We need to stop treating math like some unlearnable alien language—you'd still need to learn it anyway, regardless of what you call the abstractions. Also in many (perhaps most) cases there is no clear choice for the "friendly" term. Words like "chainable" would be highly ambiguous, as many different types of abstractions support some notion of "chaining". This would likely result in bikeshedding and more divergence in terminology and less precision in meaning.
If you think the math terms are bad, try asking a mathematician to rename the terms in their field. They'll tell you the same thing.
You really think functional programmers don't build composite types?
Lambda calculus, category theory, and logic are essentially 3 sides of the same coin (the Curry-Howard-Lambek correspondence). The rules of lambda calculus match those of natural deduction. It runs quite a bit deeper than you're suggesting here. It's not just some arbitrary formalism.
> And yes it has everything to do with AI
No, category theory is not about AI. My training was certainly sufficient for me to refute that connection, and the way you keep referring to my "training" rubs me the wrong way.
> Category Theory (at least applied to computing) studies how instructions are assembled into running programs.
Um, no? As a software engineer who has studied category theory, I use it mostly for denotational reasoning about programs, and to inform type-level decisions. It has nothing to do with "instructions". Perhaps a generous interpretation of this statement would be that monads, one very specific concept in category theory, can be used to model imperative programs—but that would be highly reductionist.
> That’s not to say that FP is useless. FP is obviously quite useful in many situations - but perhaps not be enough to displace the central role of wrapper functions / lambda calculus.
What? Functional programming _is_ lambda calculus. The idea of it displacing lambda calculus makes no sense.
> Why? Mathematically speaking, Category Theory is basically the same as Relational Theory (at least applied to Sets).
Oof. Rel is one category; Set is another.
> There is this fanciful notion of a “computational trinity”- the idea is that devs can somehow write to a single source of “truth” and let artificial intelligence / automation decide how it gets translated to hardware.
No, the trinity refers to the connections between category theory, logic, and programming. It has nothing to do with AI.
Was this article written by an AI?
Yes, to me it does. I love when variables have really tight scopes so I don't need to worry about if/how they are used throughout the rest of the program. Locality should be the default, not something that needs to be justified.
Creating a function is just unnecessary boilerplate if the code is not going to be reused. Functions are just named blocks with arguments. But if you don't need to name the block and don't need to reuse it with varying arguments, creating a function is just unnecessary.
Functional programmers are familiar with a concept called "let", which essentially gives you a way to introduce a variable and introduce a new scope just for that variable. This article is essentially just showing how to do that in JavaScript.
Ugh, that's not how big O notation works.
I didn't see anything about formal verification in the rest of the documentation. Does it have dependent types? Does it have a model checker? Does it have anything that would allow me to verify mathematical properties of my code?
If functions are curried, then I suppose the syntax for `f x y` would be `y.(x.f)`, which maybe you could write as `y.x.f` if the associativity worked as such. But that means you have to provide your arguments in reverse order?
If functions are not curried, do you write `(x, y).f`?
Here's something I can express with static typing that I can't express with dynamic typing: "this function returns a function which returns an integer for every input". There's no test you could write to verify this property. So I'm inclined to say that static typing is more expressive, since it gives me a way to express and verify properties like this.
I want a shirt with this on it.
I associate verbosity with object-oriented programming, whether statically typed or not.
The claim is true: a type system _can_ prevent null-related issues and eliminate the need to account for them in tests. That's not the same as saying every type system does.