Hacker News new | ask | show | jobs
by pron 664 days ago
> It is a program when I can do java tlatk.TLC someprogram.tla.

TLC is a program that takes TLA+ formulas as input and produces an output. I have a program that reads newspaper articles out loud. Doesn't make those articles programs or their authors programmers.

> Is there a difference? No

You're using implication in the wrong direction. Some mathematics can indeed appear in a programming language, but the question is not whether there's something in TLA+ that could be in Python or whether you can specify a Java program in TLA+ -- of course you can. The question is whether there's something in TLA+ that cannot be in a programming language, and, indeed, there is. All Prolog programs are programs; you can run them. Not only can you not many TLA+ specifications (or mathematical formulas in general) in a similar way to a program, many mathematical formulas cannot possibly describe any program that's implementable in the real world. You can write mathematical propositions about non-computable real numbers; you can specify a decision oracle for the halting problem (and because you can do it in mathematics, you can write it formally in TLA+).

Similarly, the fact you can specify orbital dynamics in maths doesn't make it physics, and it's easy to see it's not physics because you can just as easily specify motion that breaks physical laws.

> Maybe you don't consider this programming, but people have done more with less

You can certainly run computer programs that tell you interesting stuff about a TLA+ specification, and you can even say that the existence of such programs is the source of much of the value in TLA+. But you can run interesting and useful programs that do stuff with images, yet however you want to look at it philosophically, most photographers and programmers would agree that photography and programming are two pretty different disciplines even though photographers may use software in their work.

2 comments

You can write hello world in TLA+:

Main == PrintT("hello world")

You can't write much else, because print is the only implemented command (no input commands even), but it's clearly not just a program that reads newspapers out loud. There is an execution semantics and so on, as found in typical programming languages. It would not be hard to add input, implemented as a "hack" along the lines of print, although of course TLA+ is nondeterministic like most logic programming languages so there is some tricky semantics.

I'm not saying TLA+ is a good programming language - it is more along the lines of Brainfuck or TeX, "use it only out of necessity or masochism". But at least in my book it is undeniably in the category of programming languages.

> You can write hello world in TLA+:

That's not a good example, but before I get to that, you are again using logical implications in the wrong direction. You can describe physical systems, including programs in mathematics. What makes mathematics not the same as physics or programming is that you can also describe things that aren't physical or computable. It's like you're trying to prove that New York is the United States by pointing out that if you're in NY you're in the US.

Let me write that another way: programming ⊊ mathematics.

So you can write all programs in mathematics; you cannot do all mathematics in a programming language. Therefore, to know whether TLA+ is programming or mathematics the question is not whether you can describe programs in TLA+ but whether you can describe the maths that isn't programs, and you can.

Now, the reason that your example is not good is that the PrintT operator is defined in TLA+ [1] like so:

    PrintT(x) ≜ TRUE
It has no meaning in TLA+ other than the value TRUE. It's just another way of writing TRUE. The computer program TLC, however, prints some output when it encounters the PrintT operator in a specification, but that behaviour is very much not the meaning that operator has in TLA+. TLC can equally print "hello" whenever it encounters the number 3 in a mathematical formula. There are other TLC tricks that can be used to manipulate it to do clever stuff [2], but that's all specific to TLC and not part of the TLA+ language.

You could, however, have pointed out that you can specify a Hello, World program in TLA+, only that is unsurprising because you'd specify it in mathematics, and mathematics can also specify a Hello, World program. Here's how I would specify such a program in TLA+ (ignoring liveness for the sake of simplifying things):

    VARIABLE console
    Spec ≜ console = "" ∧ □[console' = "Hello, World!"]_console
It means that a variable named console (which we'll take to represent the content of the console) starts out blank, and at some future point its content becomes "Hello, World!" and it is not changed further.

You could also specify it another way, say, represent the console as a function of time (I'll make it discrete for simplicity):

    console[t ∈ Nat] ≜ IF t = 0 THEN "" ELSE "Hello, World!"
[1]: https://github.com/tlaplus/tlaplus/blob/0dbe98d51d6f05c35630...

[2]: I've even given a talk about such tricks: https://youtu.be/TP3SY0EUV2A

> the PrintT operator is defined in TLA+ like so

No, it is defined like so: https://github.com/tlaplus/tlaplus/blob/0dbe98d51d6f05c35630... This is the same strategy that Haskell uses for its primops, a placeholder file and implementation in another language. I guess you didn't understand my point that it would be easy to extend TLA+/TLC to more primops, like memory, a Java FFI, and so on, making it a fully featured programming language. I don't care what "the TLA+ language" is, C++ implementers regularly toss the spec in the dumpster and just like you have C++/LLVM and C++/GCC there similarly is a dialect of TLA+ for each implementation.

> No, it is defined like so

No, you are looking at the TLC source code, not TLA+ definitions. If you read the TLC documentation, it makes it very clear that it is not TLA+, but a software tool for model checking a certain subset of TLA+ and has some programming-like features that are not in TLA+. Other TLA+ tools also focus on other TLA+ subsets and have their own features, and they're not necessarily consistent with one another.

> This is the same strategy that Haskell uses for its primops

It really isn't, because TLC isn't the TLA+ compiler/interpreter. In TLA+ PrintT is just synonym for TRUE. We can talk about TLC if you like, but you shouldn't confuse the two.

> I guess you didn't understand my point that it would be easy to extend TLA+/TLC to more primops

TLA+ and TLC are two different things. TLA+ is a formal language for writing mathematical specifications. TLC is one of the several tools for analysing TLA+ specifications written in a subset of TLA+.

> I don't care what "the TLA+ language" is

That would sort-of made sense if TLC was the canonical tool for analysing TLA+ but it isn't (certainly not in the sense that ghc is the canonical Haskell compiler). In SANY, TLAPS, and Apalache (another TLA+ model checker), PrintT is just TRUE. In our work on the TLA+ toolbox, we're always careful to separate what's TLA+ and what are the features of the software tools, and in the materials we produce about TLA+ and the TLA+ tools these differences are explained.

In other words, you -- as someone who doesn't know TLA+ -- may not care about what TLA+ is and what TLC is, but those who use TLA+ very much care (though maybe not in the first week), because that distinction is required to put the language to good use.

If you choose to learn TLA+, I'm confident you'll come to agree. Everything I've said here will become clear once learn TLA+, TLC, and TLAPS (or even just TLA+). Those who actually use TLA+ very much do care what "the TLA+ language" is and what are some TLC features, because they often want to use multiple tools to do different things with their specifications, and PrintT only prints stuff when you're using TLC, not, say, when you're using TLAPS or Apalache. Once you gain experience with TLA+ you understand which subset of it can be checked by TLC and which isn't, and you write certain specifications with the intent of checking them in TLC and others for other uses, as you know that they fall outside TLC's subset of TLA+.

I think this short talk I gave and I linked to before (https://www.youtube.com/watch?v=TP3SY0EUV2A) gives a sense of the different ways you use TLA+ and how you combine them. It shows how you use the language as you do ordinary maths -- by manipulating formulas on paper -- and then use the results in conjunction with TLC to obtain some particular kind of automation. In fact, it is about how to use TLA+ to rewrite some TLA+ specifications so that they could be checked in some interesting way by TLC, i.e. the whole premise is that TLA+ users are confronted by the differences between TLC and TLA+, and it shows how to use certain deductions in practice to put TLC into some interesting uses for kinds of TLA+ specifications that TLA+ users would normally think fall outside the bounds of TLC. Anyway, anyone who actually uses TLA+ is -- and needs to be -- very much aware of the differences between TLA+ and TLC, recognises their different roles.

> If you read the TLC documentation, it makes it very clear that it is not TLA+.

Fine, clearly you are missing the point I am making about how languages become confused with implementations. Just s/TLA+/TLC/ in all the above. Is TLC a programming language implementation or not? Consider for example https://github.com/will62794/tlaplus_repl which evaluates TLC expressions. At what point is there sufficient programming language functionality for you to become convinced that TLC is a programming language?

TL;DR: Of course TLA+ can be used to describe all programs, as can all sufficiently-rich mathematical formalisms (regardless of TLC; TLC has got nothing to do with that). It is definitely not a programming language because its expressive power comes from its ability to describe things that cannot be computed (or practically computed). I.e. it's not a programming language not because it's too small of a subset of programming, but rather a vastly larger superset of programming. In other words, TLA+ (and mathematics in general) is not a programming language not because it is less than a programming language but because it is more. If TLA+ is a programming language, then so is any rich mathematical formalism, any drawing tool, or English for that matter.

> Is TLC a programming language implementation or not?

Ok, so first of all, TLC is not "an implementation of TLA+" and not because it can only check a limited subset of TLA+.

To sho that, let me take a short but important detour. What is the purpose of a computer program? It is to produce an output, either for yourself or for others you give the program to. In contrast, what is the purpose of a TLA+ specification, i.e. what is it that you do with it, or what is the deliverable? Clearly, it's not some output because a TLA+ specification has no output (I'll get back to TLC in a moment). Once you're convinced that the TLA+ specification fulfils the propositions you're interested in -- either by inspection, formal manipulation and proof on paper, formal proof checked by TLAPS, or a successful run of TLC -- the deliverable is the TLA+ specification itself, the set of formulas, whose purpose is then for someone (maybe yourself or someone else) to use as a design for some system to build -- a program, a computer chip etc.. So a the purpose and deliverable of a TLA+ specification is it itself, just like the purpose of an architectural blueprint.

Now, back to TLC. TLC is, no doubt, a program that takes as an input a TLA+ specification written in a particular subset of TLA+ and some additional configuration that defines the boundaries of state space to model-check, and produces an output that's either TRUE or a counterexample. There are other modes of running TLC, as well, for which special operators like PrintT can be useful.

Note that there are many other programs that do something with a piece of mathematics and produce an answer. The simplest one is a calculator. A calculator is a program that takes as an input some portion of a mathematical statement in a small subset of mathematics (arithmetic on some finite subset of integers and rationals) and produces an output.

So we can take a partial mathematical statement 3 + 4 and use it, in conjunction with a calculator, as a program that produces the output 7.

So finally, we can answer your question. TLC is a program that's more sophisticated than ordinary calculators, and we can certainly write some mathematical statements in a subset of TLA+ so that when we feed them into TLC we create some interesting output. It is similar to a CAD/CAM tool you run on an architectural blueprint. But is the tool "an implementation" of the blueprint? I don't think that makes sense.

> At what point is there sufficient programming language functionality for you to become convinced that TLC is a programming language?

TLC is not a language but a tool that can process a subset of TLA+. The existence of calculators or of TLC does not mean that mathematics is a programming language, because:

1. Even though mathematics can be used to describe all programs and all of physics -- because the domain describable by mathematics, and therefore by TLA+ -- is a superset of all the behaviours of physical and computable things, it is also a strict superset, and mathematics (and therefore TLA+) can describe lots and lots of things that cannot possibly be realised by anything in the physical world or by any computation.

2. Even though some subset of mathematics (and therefore of TLA+) can be used in conjunction with some program to produce an intended output, that output is not the purpose of mathematics (and therefore of TLA+).

As for 1, you may then ask what's the point of a language that is ultimately intended to produce designs for physically-realisable systems to encompass all of mathematics and describe things that are not realisable. There are two answers to that: first, it makes the working with the language much simpler, just as working in classical mathematics is simpler than working in constructive mathematics (which is based on intuitionistic or some other constructive logic rather than classical logic). Second (and this is really an application of the first answer), specifying non-realisable things is helpful when specifying properties of realisable things. For example, suppose you design an algorithm that can decide whether some specific subset of programs halt. You want to check the proposition that:

    InMySubset(InputProgram) ⇒ MyAlgorithm(InputProgram) = Halts(InputProgram)
and to do that you need to describe the operator Halts even though it is not realisable (as it's not computable). So Halts clearly cannot be written as a program, yet defining it in some mathematical formalism is needed to express a real property of a real program. (BTW, the definition of a Halts operator is a trivial one-liner in TLA+ [1]).

I see that again and again you're getting stuck on the point that because there are programs that can evaluate mathematical statements, mathematics is a programming language. But the fact that you can describe any program or any physical system in mathematics is the point and power of mathematics. But mathematics is neither physics nor programming because it can also describe things outside the world of programs and physics.

Of course you can write programs in every rich mathematical formalism, including TLA+ (and TLC has nothing to do with it; this would be true even if TLC didn't exist). But programming languages are languages that can describe things that live in a small subset of the world of mathematics. TLA+ is not a programming language not because it doesn't contain the universe of all programs -- it does; every imaginable program could be specified in mathematics and specifically in TLA+ -- but because it contains much, much more.

So if you want to define "a programming language" as any language in which you could describe many or perhaps even all computations, then every rich mathematical formalism (and therefore TLA+) could be considered a programming language. But I would think that a language where most things you write are not computable isn't a programming language. Rather, a programming language is one where everything you write in the language is at the very least computable, and that is certainly not the case for TLA+.

Something similar is true for English. You can use English to describe any conceivable algorithm, and there are now tools that could convert a subset of such descriptions to executable software. But the fact you can use English to describe programs doesn't make English a programming language, because many of the things it is used to described aren't programs.

But even if you insist that mathematics (or English) is a programming language, the point is still that mathematics (and TLA+) exists to describe useful things that go well beyond what could be described in a programming language [1].

[1]: Halts(Program, vars) ≜ Program ⇒ ⬦□(vars' = vars)

[2]: I'm overlooking the type level in programming languages with rich type systems (like Agda), but the point still stands, only the details are more technical.

P.S.

There's another interesting distinction to be made between Idris, a programming language that can also express a lot of maths, and TLA+, a mathemtatical language that isn't a programming language.

Languages like Idris make a sharp distinction between the type level and the object or computation level. The type level can express something analogous to the propositions you can express with TLA+, but these propositions must be filled or "realised" with content at the object level, and that content is required, even at the syntax level, to be a program, i.e. something that is executable.

In TLA+, in contrast, there's only a "type level". You can define refinement relationships between different specifications -- i.e. one is a more detailed description of the other -- but there is no requirement that any level needs to be executable. It may just so happen that some specification are detailed enough to extract a computation from (same goes for mathematics in general), but that's not a requirement.

BTW, it is interesting to note (as I do here in more detail: https://pron.github.io/posts/tlaplus_part3#algorithms-and-pr...) that quite often even simple algorithms -- I give QuickSort as an example -- that are described in a way that's detailed enough for a human to implement and perhaps even a computer could extract a reasonable computation from, are still not a program. The QuickSort algorithm says nothing about how to pick a pivot because any choice would still be an implementation of QS, even though a program must pick a pivot somehow and some choices may be better than others, nor does it describe in what order to sort the two segments -- they could be sorted in any order or even in parallel. For there to be a program, the computer must ultimately be told these details. Still, the algorithm is specified without them, as they don't matter to the algorithm itself, and it can be formally specified in TLA+ without them. If you choose, you may specify a particular and less abstract implementation of QS in TLA+ and check that it is, indeed, an implementation of the more abstract algorithm.

This could be seen as analogous to the object level in a programming language with dependent types, but the difference is that in TLA+ it's not required nor is there a clear distinction between a level of detail that is executable and one that isn't.