Decidable and Turing-Recognizable Languages
Imagine handing a computer a description of another program and a claimed property. You ask it to answer yes or no. It must always answer, correctly, and in finite time. This is the question that separates the languages a machine can decide from the languages it can merely recognize. Some problems admit an algorithm that always halts with the right verdict. Others admit only a procedure that confirms "yes" when the answer is yes. Such a procedure may loop forever on "no" instances. It never tells you to give up. This distinction is not a technicality. It is the central fault line of computability theory. It explains why some real problems are fully automatable. For example, testing whether a regular expression matches a string is fully automatable. Other problems can only be approximated, never fully solved by a general algorithm. Examples include testing whether an arbitrary program halts. Another example is testing whether a compiler optimization preserves behavior. Understanding deciders versus recognizers is the prerequisite for everything that follows in the theory of unsolvability. The Halting Problem, reductions, and the arithmetic hierarchy all rest on this vocabulary. The big picture is a hierarchy of language classes. These classes are built directly from the notion of a Turing Machine computing on a configuration sequence. A Turing machine can accept, reject, or run forever on a given input. Depending on which of these behaviors we permit and which we forbid, we get different classes. These are the decidable languages (also called recursive), the Turing-recognizable languages (also called recursively enumerable, r.e., or semidecidable). As a preview, there are also the co-Turing-recognizable languages. Their relationship to decidability will be developed once closure properties are in hand. This article delivers precise definitions of deciders and recognizers. It offers a careful proof that decidable languages form a strict subset of recognizable languages. It presents worked machine constructions. These show how to convert between semi-decision procedures and search-based enumeration. Finally, it gives an honest discussion of why the gap between the two classes is unavoidable. This gap is not a defect of imagination.
- A decider is a Turing machine that halts on every input, always outputting accept or reject.
- A recognizer only guarantees halting and accepting on "yes" inputs; on "no" inputs it may reject or loop forever.
- Decidable (recursive) languages are exactly those recognized by some decider.
- Turing-recognizable (recursively enumerable) languages are exactly those recognized by some Turing machine, decider or not.
- Every decidable language is Turing-recognizable, but not conversely — the containment is strict.
- The strictness is witnessed concretely by the Halting Problem language, which is recognizable but not decidable.
A language is decidable if some machine always halts and answers correctly, but merely Turing-recognizable if some machine halts and answers correctly only on the "yes" instances.
The idea
A Turing machine processes an input string by running through a sequence of configurations, as established when configurations and single-step computation were defined. On any fixed input, exactly one of three things happens: enters its accept state and halts, enters its reject state and halts, or runs forever without halting. This trichotomy is the raw material from which the entire vocabulary of computability is built. Call a decider if, for every input string , halts — either accepting or rejecting — and never loops forever. A decider gives you a complete, guaranteed verdict on every input; this is the strongest and most desirable behavior an algorithm can exhibit. A language is decidable (equivalently, recursive) if there exists some decider with , meaning accepts , and additionally halts on every (accepting members of and rejecting everything else). Call a recognizer for language if , with no further requirement: must accept every , but on strings , is permitted either to reject or to run forever. A language is Turing-recognizable (equivalently, recursively enumerable, or r.e., or semidecidable) if some Turing machine recognizes it. The word "semidecidable" captures the asymmetry precisely: only the "yes" side of the decision is guaranteed to terminate. The crucial structural fact is that every decider is automatically a recognizer — a machine that always halts correctly is in particular a machine that accepts exactly the members of (it just happens to also reject everything else with a guarantee). This immediately gives
The heart of computability theory is the discovery that this containment is strict: there exist languages that are Turing-recognizable but not decidable. The canonical witness is
the language underlying the Halting Problem's acceptance variant. is Turing-recognizable — simulate on and accept if the simulation accepts — but no decider for can exist, by a diagonalization argument. This single example is the seed from which nearly all undecidability results grow via reduction.
How it works
The clean way to see the relationship between deciding and recognizing is to build the machines explicitly and to prove the equivalence theorem that connects "recognizable" to "there is an algorithm that enumerates the language."
Building a recognizer from a machine that simulates another machine. Given the encoded pair , a universal recognizer simulates step by step on : ``` procedure Recognize-ATM(⟨M, w⟩): // U is a universal Turing machine: it interprets M's transition // table and simulates M running on w, one configuration at a time. initialize configuration C0 := start configuration of M on w C := C0 loop forever: if C is an accepting configuration of M: accept if C is a rejecting configuration of M: reject C := next configuration of M from C // one simulated step // if M loops forever on w, this loop never halts — that is fine // for a recognizer, but would violate the decider requirement ``` This machine is a legitimate recognizer for : whenever accepts , the simulation eventually reaches an accepting configuration and accepts; whenever rejects , rejects; whenever loops on , loops too. never gives a wrong answer, but it fails the decider requirement precisely on the looping case — it does not halt there.
Why you cannot simply "wait longer" to fix this. A natural instinct is: run for more and more steps, and if it hasn't halted, guess "no." This is unsound, because for any finite bound , there exist machine-input pairs that take more than steps to accept. Any fixed cutoff misclassifies some accepting instance as rejecting. There is no way to distinguish, by looking only at a finite prefix of the computation, "still working" from "will never finish."
The Enumeration Theorem. A deeper structural fact makes "Turing-recognizable" synonymous with "the language of accepted strings can be listed by an algorithm, possibly with repetition and without a guarantee of ever hitting a given non-member." Formally: is Turing-recognizable iff there is a Turing machine (an enumerator) that, running with no input, prints out a sequence of strings (with possible repeats, in any order, possibly running forever) such that is exactly the set of strings that eventually get printed. From enumerator to recognizer: given , build that on input runs , and whenever prints a string, checks whether it equals ; if so, accepts. If , it will appear in 's output eventually, so accepts; if , simply never accepts (it loops), which is exactly recognizer behavior. From recognizer to enumerator — the dovetailing trick: this direction is the more delicate and instructive one, because a naive attempt fails. Given recognizer , you cannot just "run on , then , then …" because might loop forever on if , and you would never get to try . The fix is to dovetail: interleave a growing amount of simulation time across a growing set of candidate strings. ``` procedure Enumerate(M): // M is a recognizer for language L, over some fixed alphabet Σ. // s1, s2, s3, ... is the standard enumeration of all strings in Σ* // in length-then-lexicographic order (so every string appears at // a specific finite index). for i := 1, 2, 3, ...: for j := 1 to i: simulate M on input s_j for exactly i steps if M accepts s_j within those i steps: print s_j // may print duplicates; that is allowed ``` Every pair with is visited exactly once as ranges over all positive integers, so for any fixed string that accepts within steps, the pair (or any ) is eventually reached, and gets printed. Strings not in are never printed, because never accepts them regardless of how long it runs. This establishes the equivalence in both directions.
Complexity & correctness
Deciders. If is a decider running in steps on inputs of length , deciding membership costs time and space where is the space uses — these bounds are exactly the resource bounds studied later under Time Complexity and space complexity. The definitional claim here is not about a specific bound but about guaranteed termination: for every , the computation of on is a finite sequence of configurations ending in accept or reject. This is an all-quantified halting guarantee, and it is what makes decidability a robust, checkable-in-principle property from the outside — you can always ask "has it halted yet?" and eventually get a truthful "yes."
Recognizers. A recognizer gives no uniform bound on halting time as a function of alone — indeed for a fixed length there can be no computable bound, since if there were, you could decide the language by running for that many steps and rejecting if it never halted, contradicting undecidability of languages like . So the "complexity" of a mere recognizer is unbounded on the reject side; only accepting runs are guaranteed finite, and even then with no known bound in advance.
Correctness of the enumerator/recognizer equivalence. The proof sketch above is a full correctness argument, but it is worth stating the invariant explicitly. In the dovetailing enumerator, the invariant maintained after completing outer iteration is: > For every and every string that accepts within steps, has already been printed. This invariant holds by direct execution of the nested loop (the inner loop at outer index explicitly simulates for steps for every ). Taking , every string eventually satisfies " accepts within steps" for large enough (namely ), so it is printed at that stage or later. Conversely no is ever printed, since printing only happens upon a genuine accept by 's simulation. This is exactly the semantics of Turing-recognizability, establishing the equivalence rigorously rather than by analogy.
Why decidable recognizable, not just . The inclusion direction is immediate (a decider is a recognizer). Strictness needs a genuine diagonalization, sketched here because it is the load-bearing fact of the whole subject. Suppose, for contradiction, that had a decider : always halts, accepting iff accepts . Construct : ``` procedure D(⟨M⟩): if H(⟨M, ⟨M⟩⟩) accepts: // does M accept its own description? reject else: accept ``` is well defined and always halts, because is assumed to always halt. Now ask what does on its own description :
- If accepts , then by 's definition rejected, meaning does not accept — contradiction.
- If rejects , then accepted, meaning does accept — contradiction.
Both cases are contradictory, so no such can exist. Hence is undecidable. But is Turing-recognizable (the universal simulator above recognizes it), which exhibits a concrete language in Turing-recognizable minus decidable, proving the containment strict. This argument is the direct descendant of Cantor's diagonal argument against a bijection between a set and its power set, transplanted into the world of machine descriptions.
Tradeoffs, honestly stated. Decidability is the gold standard but is a strong requirement that many natural questions fail to meet; recognizability is a weaker, more common guarantee that still has teeth (it supports semi-automated verification: run and wait, and if it says yes, trust it). The class of decidable languages is closed under complement, union, and intersection — because you can build a decider for the complement by simply flipping the accept/reject roles of a decider, which halts on everything by hypothesis. Turing-recognizable languages are closed under union and intersection (dovetail two recognizers) but not guaranteed closed under complement, which is exactly the seed of the co-Turing-recognizable class and its relation to decidability, taken up separately.
Worked example
Consider three concrete languages over machine encodings, tracing what kind of machine each admits.
Language 1: is a DFA that accepts string .
| Step | What the decider does |
|---|---|
| 1 | Parse into a DFA description and a string. |
| 2 | Simulate on : start at 's start state, read symbol by symbol, follow transitions. |
| 3 | Because is finite and each symbol read strictly advances the simulation, this loop terminates after exactly transitions. |
| 4 | Accept if the final state is accepting; reject otherwise. |
This machine always halts — the simulation is bounded by steps with no possibility of looping, since DFA computation is a straight-line walk through states with no branching or backtracking. Hence is decidable.
Language 2: accepts , as above.
| Step | What the universal recognizer does |
|---|---|
| 1 | Parse . |
| 2 | Simulate step by step on , updating the simulated configuration each time. |
| 3 | If a simulated step reaches accept, halt and accept. |
| 4 | If a simulated step reaches reject, halt and reject. |
| 5 | If never halts on , the simulation runs forever — no fallback exists. |
This machine recognizes but is not a decider, precisely because step 5 can occur (e.g. is a machine that loops on all inputs, so and the simulator hangs). By the diagonalization argument above, no decider for exists — this failure is unavoidable, not a limitation of this particular construction.
Language 3: ("does accept nothing at all?"). Trying the naive approach — dovetail over all strings and see if it ever accepts — gives a recognizer for the complement (accept if you ever witness accept something), but gives no recognizer for itself in any obvious way, and in fact can be shown Turing-recognizable-but-not-decidable by reduction from , foreshadowing the reduction technique used pervasively once decidable problems about automata are studied in depth. The three languages above thus stratify exactly the classes this article defines: fully decidable (), recognizable but not decidable (), and a further example () whose non-recognizable complement will matter once closure under complement is examined.
A second trace, showing dovetailing concretely. Suppose alphabet and is a recognizer such that accepts after exactly steps of simulation (a toy stand-in for "acceptance time grows with input"). Enumerate
| Outer | Inner | Steps given to | accepts within budget? | Printed? |
|---|---|---|---|---|
| 1 | 1 | 1 | needs 2, no | no |
| 2 | 1 | 2 | needs 2, yes | |
| 2 | 2 | 2 | needs 4, no | no |
| 3 | 1 | 3 | already printed, printed again | print (duplicate, harmless) |
| 3 | 2 | 3 | needs 4, no | no |
| 3 | 3 | 3 | needs 6, no | no |
| 4 | 2 | 4 | needs 4, yes | |
| 4 | 3 | 4 | needs 6, no | no |
| 4 | 4 | 4 | needs 8, no | no |
| eventually every printed at |
Every string eventually gets enough simulated steps to reveal its true accept time, so the enumerator prints exactly (with repeats), matching exactly, as the general argument guarantees.
Common pitfalls & traps
| Pitfall | Why it's wrong | Fix |
|---|---|---|
| Treating "recognizer rejects" and "recognizer loops" as the same outcome | A recognizer is allowed to loop on non-members; conflating loop with reject silently upgrades it to a decider it may not be | Always state separately: accept guarantee, reject-or-loop on non-members |
| Believing you can "wait long enough and then reject" | No computable bound on halting time exists uniformly for an arbitrary recognizer; assuming one exists effectively assumes decidability, begging the question | Only convert to a decider if you have an independent proof of a halting bound |
| Assuming Turing-recognizable is closed under complement | It is not, in general — is recognizable but is not, a fact that becomes central once co-recognizable classes are studied | Don't reuse decidable-class closure arguments for the recognizable class without separate proof |
| Confusing " halts on this particular " with " is a decider" | Decider-ness is a property of the whole machine over all inputs, not a single run | Check the universally quantified halting condition, not one instance |
| Building an enumerator by running on sequentially without interleaving | If loops on some early , the whole enumeration stalls forever and later members of are never listed | Use dovetailing: bound simulation steps per candidate and grow both the candidate pool and the step budget together |
Pioneers & history
The vocabulary of deciders, recognizers, and the boundary between them emerged directly from foundational work on the limits of mechanical computation in the 1930s, tightened and formalized over the following decades into the standard hierarchy taught today.
Origins · 1 minAlan Mathison Turing and how this was discovered
Where this matters
Every practical verification and analysis tool lives on one side of this line or straddles it deliberately. Type checkers for languages with decidable type systems (Hindley–Milner inference in ML-family languages) are deciders — they always terminate with a definite yes/no on whether a program type-checks. Model checkers for finite-state hardware and protocols exploit decidability of automaton-based questions (emptiness, equivalence) to give guaranteed answers about bounded systems. Static analyzers and linters for general-purpose languages, by contrast, typically implement recognizer-style or approximate procedures for properties like "does this code path ever execute," because the exact question is undecidable by reduction from the halting problem; industrial tools accept this and report either a sound over-approximation or "unknown" rather than looping forever. SAT and SMT solvers are deciders for their respective decidable theories, underlying modern compiler optimizations, program synthesis, and hardware verification pipelines. Theorem provers like Coq, Lean, and Isabelle formalize proofs whose checking is decidable (a fixed, finite proof object is verified in bounded time) even though finding the proof is not guaranteed to terminate — exactly the decider/recognizer split relocated to proof search versus proof checking. Understanding this boundary is also what lets engineers recognize, before writing code, that a proposed feature ("detect all infinite loops in user-submitted code and reject them") is asking for something no algorithm can deliver in full generality, redirecting effort toward sound approximations instead.
Ask the tutor: If a language and its complement are both Turing-recognizable, what can you conclude about the language itself, and why?
What exactly is the difference between "Turing-recognizable" and "recursively enumerable"?
Nothing mathematically — they are two names for the same class of languages, arising from two different historical traditions. "Turing-recognizable" (or "semidecidable") comes from automata-theoretic phrasing centered on machine behavior: accept, reject, or loop. "Recursively enumerable" comes from recursion theory, emphasizing that the language can be enumerated (listed) by an algorithm, possibly without ever halting overall. The Enumeration Theorem in this article proves these two descriptions coincide exactly, which is why textbooks use the terms interchangeably once the equivalence is established.
If a language is decidable, does that mean we know a fast algorithm for it?
No — decidability only guarantees the algorithm halts on every input, with absolutely no bound on how long that might take. A language can be decidable yet require exponential, or even non-elementary, time in the worst case; deciding is purely a qualitative, unbounded-resource guarantee. Questions of how fast a decidable language can be decided belong to time and space complexity theory, layered on top of decidability, not a substitute for it. A language being "decidable in principle" and "decidable efficiently in practice" are entirely separate claims, and conflating them is a common beginner mistake.
Can a language be neither decidable nor Turing-recognizable?
Yes, and in fact almost every language is like this. There are only countably many Turing machines (each has a finite string description), so there are only countably many recognizable languages, but there are uncountably many languages over any nonempty alphabet, by a diagonal cardinality argument on infinite binary strings representing membership. The complement of , written , is a concrete example that is not Turing-recognizable at all, which becomes the entry point for the co-Turing-recognizable class studied alongside closure properties.
Is checking whether a given proof is correct the same kind of problem as finding a proof?
No, and this is exactly the decider/recognizer split in disguise. Checking a fixed, finite candidate proof against inference rules is decidable — you can always finish and report valid or invalid in bounded time relative to the proof's size. Searching for some proof of a given statement, however, is only semidecidable in general: if a proof exists you will eventually find it by systematic search, but if no proof exists, the search may never terminate and tell you so. This asymmetry is why automated theorem provers can confirm true statements but cannot, in general, certify unprovability.
Does every Turing-recognizable language have a "nice" enumerator that lists strings in sorted order?
Not necessarily in increasing length or lexicographic order without extra structure — the dovetailing enumerator described here may print strings out of natural order and with repeats, because it is driven by simulated acceptance times rather than string order. If you additionally require the enumerator to output strings in strictly increasing order without repetition, the resulting notion is sometimes called an enumerator in canonical order, and it turns out a language admits such an enumerator if and only if it is decidable — printing in guaranteed sorted order effectively forces you to know when you've seen everything up to a point, which is a decidability-strength guarantee.
How does this relate to the Halting Problem specifically?
The Halting Problem, usually phrased as , is Turing-recognizable by the same universal-simulation idea (run on , accept once it halts, loop if it never halts) but is provably undecidable by essentially the same diagonalization used for in this article. In fact and are computably equivalent — a decider for one yields a decider for the other via straightforward reduction — so they serve as interchangeable canonical examples of the recognizable-but-undecidable class, and both anchor the broader theory of reductions used to prove other languages undecidable.
Why does this matter if I'm never going to write a Turing machine by hand?
Because the theorems here transfer, via the Church–Turing thesis, to any real programming language or computational model you will ever use. Whenever a static analysis tool, a build system, or a compiler claims to "detect" some general behavioral property of arbitrary code — infinite loops, unreachable code in full generality, exact resource usage — this theory tells you in advance whether a complete, always-terminating solution can exist at all. Recognizing the decidable/recognizable boundary lets engineers ask for the right kind of guarantee (a sound approximation, a bounded-input decision procedure) instead of chasing an algorithm that provably cannot exist.