solomonb
Joined 7 years ago
Joined 7 years ago
That isn't entirely true when it comes to dependent types and can be seen as a design choice. Types can depend on values and those values can often exist at runtime. Erasure only applies to parts we can determine are not computationally relevant.
For example `Vec n a`. The `n` is a natural number you may need at runtime, such as to get the length without walking the list. A dependent pair `Sigma(n : Nat). Vec n a` carries that `n` at runtime as ordinary data.
In fact many dependently typed languages have techniques, such as quantitative type theory, to assert what is needed at runtime.
Honestly I can't believe I even need to state this. Its literally how science works..
Thinking in such a utilitarian way feels like a flavor of Meditations on Moloch.[1] Just look at how short-term, quarter-to-quarter thinking is affecting the economy and the lived experience of every human on earth. It’s horrible.
[1] https://slatestarcodex.com/2014/07/30/meditations-on-moloch/
Why is this the argument when someone challenges your source, but when it comes to someone else's source your argument is:
> This is research from a labor advocacy group, with the explicit aim of the organization to advocate for this sort of thing. This doesn't mean the research is is automatically invalid, but it is bias worth mentioning.
You can can read from Loki or Journald and use regex or alert levels to filter what you pass to the LLM.
I've been using it with deepseek for my homelab. Its pretty helpful.
> I'm going to be thinking about that for a while.
This is a deep and fascinating world to get into. Enjoy!
> It led me to a kind of branching, graph-like manner of learning...
Yes! I love this experience. It takes a little owrk but you can even import the 1lab as a library and re-implement whatever fragment of it you are trying to learn. Working through a proof using a proof checker is an amazing experience and is actually really fun.
The real learning (about the thing you are proving but also about type theory, programming language design, abstraction, etc) occurs while interactive with the proof checker. They all come with really sophisticated tools for interacting with the compiler and the code, interactions that are rather unlike any other ide experience.
If you wanted a place to get started I would highly recommend PLFA: https://plfa.github.io/
> An interactive textbook as a computational medium I feel has a lot more potential for usefulness and expression
I agree 100%. PLFA is a great example of something in that direction but I think we could go a lot further. I've fantasized forever about something like the illustrated primer from Neal Stephenson's The Diamond Age (https://en.wikipedia.org/wiki/The_Diamond_Age). I think that LLMs + dependently type languages could get you close to it.
I think many people here might be surprised by what writing proofs in Lean/Agda/Rocq/Idris is actually like.
If you have only seen a giant wall of proof output from an LLM then it probably looks like writing some kind of alien "assembly language for math." This couldn't be further from the truth. These are very high level functional languages with sophisticated developer tooling.
Working with a proof checker does more then help you understand the thing you are proving. It teaches you about abstraction, software design, and type theory. I strongly believe this makes you a better software engineer. Its also surprisingly fun and game like!
From what I understand the Lean community leans (haha) classical and uses these axioms throughout mathlib. By staying constructive you guarantee that closed proofs can, in principle, evaluate to a canonical form.
For anyone reading this, here is a very small example proof that + is associative over Nats in Agda (written using 1lab style equational reasoning syntax):
+-associative : (x y z : Nat) → x + (y + z) ≡ (x + y) + z
+-associative zero y z = refl
+-associative (suc x) y z =
suc x + (y + z) ≡⟨ ap suc (+-associative x y z) ⟩
suc (x + y + z) ≡⟨⟩
(suc x + y) + z ∎
We pattern match on the first nat to get `zero` and `suc x`. In the `zero` case we have `0 + (y + z) = (0 + y) + z`. Both sides compute to `y + z` and thus the equation holds by reflexivity.In the `suc x` case we need to show that `suc x + (y + z) ≡ (suc x + y) + z`.
`suc x + (y + z)` computes to `suc (x + (y + z))` by the definition of `+`.
By recursively calling `+-associative x y z` we get `x + (y + z) ≡ (x + y) + z`. Then we need to prove that by congruence this is true under `suc`. We get this by passing our proof (from the recursive call to +-associative) into `ap suc`. `ap` says that given `a = b` it is true that `f a = f b`.
Finally, `(suc x + y) + z` computes to `suc ((x + y) + z)`, so the last step holds by computation, which is why it’s just `≡⟨⟩`.
Proof checkers like Lean/Agda/Rocq are literally total functional programming languages with rich type systems.
Everything above comes down to pattern matching and function application. The proof is just a function whose type is the statement we wanted to prove, and the type checker accepting it is what makes it a proof.
This is the Curry-Howard Correspondence in a nutshell. Propositions are types and proofs are programs.
I also like compost.
and radio.
blog.cofree.coffee www.kpbj.fm www.kchungradio.org
ssbothwell_at_gmail_dot_com