Earlier quoted context omitted.
You do realize that you're moving part of the cognitive load until later and increasing it when you have to implement a type checker in unit tests for every program you write.
Yes and? I have the full power of the language to force type correctness instead of some janky meta language.
Rust's type system is Turing-complete (2017)
31–40 of 91 posts
Re: Rust's type system is Turing-complete (2017)
#32One of the reasons I like weak type systems or duck typing as is with vanilla JS is because I don't have cognitive overload... I don't have to think about abstractions as types I only need to think how to solve the problem in front of me. My unit tests can check for correctness after I've solved the problem. The fact that you can have Turing completeness in a type-system (not the language itself but within it's type…
Type systems are very useful to establish the semantics of your operations. For example `int + int` is not the same operation as `string + string`, and definitely not the same as `int + string` (which does not exist in most languages). You could call `+` an addition, but addition only exists for numbers, for strings it is a concatenation.
Is `int + string` the same as `string + int` ? (commutativity)
Is `int + int + string` the same as `(int + int) + string` or `int + (int + string)`? In that case, what does `int + string` returns? (associativity)
Now consider this code:
def foo(a, b):
return a + b
vs function foo(a: int, b: string) {
return a + b
}
In the second case, your function obviously seems wrong.Finally, in math an object does not "have a type" but "belongs to a set/class". For example, "1" is an integer, an odd number, a real, a complex, a scalar, a rank 1 tensor, etc... Saying that "1" is only an integer is incorrect, but that's what most programming language do.
I've tried to design a language where "typeof variable == type" does not exist but instead you have "variable isof type" running the type checking code, example:
class user(v: struct {
name: string,
logged_in: bool
})
class logged_user(u: user) check
# this code is evaluated when 'isof' is called
u.logged_in = true
end
class allowed_user(u: user) check
# =>, operators are logical connectors
# A => B is true if A and B are true or A is false
# A B is true if A and B are both true
u isof logged_in u.name in ['admin', 'root']
end
let alice = { name: 'alice', logged_in: false }
assert alice isof user = true
assert alice isof logged_user = false
assert alice isof allowed_user = false
let bob = { name: 'bob', logged_in: true }
assert bob isof user = true
assert bob isof logged_user = true
assert bob isof allowed_user = false
But lazyness got the best of me and I only implemented the parser :(Re: Rust's type system is Turing-complete (2017)
#33Earlier quoted context omitted.
I disagree. A terminating type checker is much more valuable than a possibly non-terminating one. Also I think you're possibly conflating multiple issues here. Higher-kinded types, dependent types and kind polymorphism don't actually mean your type system becomes undecidable. They do vastly complicate the implementation in other ways, though.
It's easy enough to turn a non-terminating type checker into a terminating one, just add a recursion limit.
Re: Rust's type system is Turing-complete (2017)
#34It links to Wikipedia (WP), which defines "system" by:
> a computational system (such as an abstract machine or programming language)
there is no better citation[0], because it's not true under some definitions of "computational system", per WP's definition of "computational system" [3]. For example, under the WP definition of "abstract machine", a non-computable function satisfies the definition. Or we can define it as follows: input: strings in an alphabet A, output: {true, false}, operations allowed: check for membership in a language L in alphabet A.
So we see that theoretical formal languages are a subset of computational systems. But there are uncountably many formal languages and only countably many TM. Crucially, we can easily turn each language into one that acts as a universal turing machine while still being distinct. Hence there are uncountably many Turing-complete languages for a given alphabet A[2]
[0]: incidentally, the linked WP page claims slightly differently (unimportantly) that "All known Turing-complete systems are Turing-equivalent, which adds support to the Church–Turing thesis."
[1]: "A typical abstract machine consists of a definition in terms of input, output, and the set of allowable operations used to turn the former into the latter." Absent a more precise definition, I assume the set may include arbitrary mathematical operations (and it is useful to define non-computable abstract machines, and in general usage in the field abstract machines may refer to languages more powerful than Turing machines).
[2]: Sketch: Let U' be a Universal TM in alphabet A (hence U is Turing-complete), let M' denote the language it accepts, and let 0 be a symbol of A. Define M such that if i' in M', then i in M, where i is i' with every symbol duplicated and 0 prefixed (hence if i'="123", i="0112233") Define N such that if i' in complement(M'), then i in N, where i is i' with every symbol duplicated and 0 prefixed. Observe that every language disjoint from N that contains M is Turing-complete (wrt a slightly modified description for TMs and the simulated input than the one for U'). Now, let L be an arbitrary language in A. Define f(L) = { j | j' in L, j is j' with every symbol duplicated }. Then we see that f(L), M, N are all disjoint. And if T, U are distinct languages, so (f(T) union M) and (f(U) union M) are distinct languages that simulate Turing machines (i.e. they are Turing-complete). Hence there are uncountably many Turing-complete languages. There are only countably many Turing machines, hence only countably many Turing-equivalent languages, so in fact most Turing-complete languages are not Turing-equivalent languages.
[3]: of course,
Re: Rust's type system is Turing-complete (2017)
#35To me the main takeaway of results like this is: you're already paying the full price of using whatever complicated type system feature you care to name. So I have limited sympathy for people who are scared of the complexity of, say, higher-kinded types, or dependent types, or kind polymorphism. Your type system is already as complicated as possible, adding more features won't make it more Turing-complete - rather, m…
I disagree. A terminating type checker is much more valuable than a possibly non-terminating one. Also I think you're possibly conflating multiple issues here. Higher-kinded types, dependent types and kind polymorphism don't actually mean your type system becomes undecidable. They do vastly complicate the implementation in other ways, though.
I don't think that's true at all, and I think there are two extreme examples that drive the point home:
Consider on the one hand a language where typechecking is entirely terminating so long as you don't use one particular feature; however, that feature is also not very useful in practice (even notwithstanding the potential nontermination) and so it doesn't actually get used by real people writing real code. Adding that feature doesn't improve the language, but I contend that it doesn't make the type checker "much [less] valuable."
On the other hand, consider a language where type checking provably terminates in all cases, but based on subtleties sometimes completes in seconds and sometimes takes decades. I don't think this provides "much more [value]" than a similar system that sometimes fails to terminate only in some of the cases where the other would take (say) more than a week.
Re: Rust's type system is Turing-complete (2017)
#36One of the reasons I like weak type systems or duck typing as is with vanilla JS is because I don't have cognitive overload... I don't have to think about abstractions as types I only need to think how to solve the problem in front of me. My unit tests can check for correctness after I've solved the problem. The fact that you can have Turing completeness in a type-system (not the language itself but within it's type…
I have the inverse experience. I find it far more cognitively burdensome to have to keep track of the types without annotations or assistance from a type checker. Getting rid of the type checker doesn’t make the type go away, it just means the full burden of managing them correctly falls on the programs. And it’s not for lack of effort—I’ve been using Python among other languages for 15 years, but I would still find…
Python is not Perfect (bad general-purpose performance), but IMHO honestly a more productive language than Go.
And Python has type hinting nowadays which is sweet when you want it. Type hinting is good for self-documenting stable code.
Re: Rust's type system is Turing-complete (2017)
#37> Most if not all Turing-complete systems are also known to be Turing-equivalent. (I regret not being able to find a better citation for this.) It links to Wikipedia (WP), which defines "system" by: > a computational system (such as an abstract machine or programming language) there is no better citation[0], because it's not true under some definitions of "computational system", per WP's definition of "computational…
The "All known Turing-complete systems are Turing-equivalent, which adds support to the Church–Turing thesis." thing seems to have an implied "Turing-complete systems that are physically implementable." (I edited the article to add that.)
Re: Rust's type system is Turing-complete (2017)
#38Earlier quoted context omitted.
It's easy enough to turn a non-terminating type checker into a terminating one, just add a recursion limit.
That makes it nearly impossible for the programmer to predict what will type check and what will not.
Re: Rust's type system is Turing-complete (2017)
#39Earlier quoted context omitted.
It's easy enough to turn a non-terminating type checker into a terminating one, just add a recursion limit.
That makes it nearly impossible for the programmer to predict what will type check and what will not.