Proving the inexpressibility of a function in a given language - programming-languages

I'm currently reading through John C. Mitchell's Foundations for Programming Languages. Exercise 2.2.3, in essence, asks the reader to show that the (natural-number) exponentiation function cannot be implicitly defined via an expression in a small language. The language consists of natural numbers and addition on said numbers (as well as boolean values, a natural-number equality predicate, & ternary conditionals). There are no loops, recursive constructs, or fixed-point combinators. Here is the precise syntax:
<bool_exp> ::= <bool_var> | true | false | Eq? <nat_exp> <nat_exp> |
if <bool_exp> then <bool_exp> else <bool_exp>
<nat_exp> ::= <nat_var> | 0 | 1 | 2 | … | <nat_exp> + <nat_exp> |
if <bool_exp> then <nat_exp> else <nat_exp>
Again, the object is to show that the exponentiation function n^m cannot be implicitly defined via an expression in this language.
Intuitively, I'm willing to accept this. If we think of exponentiation as repeated multiplication, it seems like we "just can't" express that with this language. But how does one formally prove this? More broadly, how do you prove that an expression from one language cannot be expressed in another?

Here's a simple way to think about it: the expression has a fixed, finite size, and the only arithmetic operation it can do to produce numbers not written as literals or provided as the values of variables is addition. So the largest number it can possibly produce is limited by the number of additions plus 1, multiplied by the largest number involved in the expression.
So, given a proposed expression, let k be the number of additions in it, let c be the largest literal (or 1 if there is none) and choose m and n such that n^m > (k+1)*max(m,n,c). Then the result of the expression for that input cannot be the correct one.
Note that this proof relies on the language allowing arbitrarily large numbers, as noted in the other answer.

No solution, only hints:
First, let me point out that if there are finitely many numbers in the language, then exponentiation is definable as an expression. (You'd have to define what it should produce when the true result is unrepresentable, eg wraparound.) Think about why.
Hint: Imagine that there are only two numbers, 0 and 1. Can you write an expression involving m and n whose result is n^m? What if there were three numbers: 0, 1, and 2? What if there were four? And so on...
Why don't any of those solutions work? Let's index them and call the solution for {0,1} partial_solution_1, the solution for {0,1,2} partial_solution_2, and so on. Why isn't partial_solution_n a solution for the set of all natural numbers?
Maybe you can generalize that somehow with some metric f : Expression -> Nat so that every expression expr with f(expr) < n is wrong somehow...
You may find some inspiration from the strategy of Euclid's proof that there are infinitely many primes.

Related

Statements vs Expressions in Haskell, Ocaml, Javascript

In Haskell, afaik, there are no statements, just expressions. That is, unlike in an imperative language like Javascript, you cannot simply execute code line after line, i.e.
let a = 1
let b = 2
let c = a + b
print(c)
Instead, everything is an expression and nothing can simply modify state and return nothing (i.e. a statement). On top of that, everything would be wrapped in a function such that, in order to mimic such an action as above, you'd use the monadic do syntax and thereby hide the underlying nested functions.
Is this the same in OCAML/F# or can you just have imperative statements?
This is a bit of a complicated topic. Technically, in ML-style languages, everything is an expression. However, there is some syntactic sugar to make it read more like statements. For example, the sample you gave in F# would be:
let a = 1
let b = 2
let c = a + b
printfn "%d" c
However, the compiler silently turns those "statements" into the following expression for you:
let a = 1 in
let b = 2 in
let c = a + b in
printfn "%d" c
Now, the last line here is going to do IO, and unlike in Haskell, it won't change the type of the expression to IO. The type of the expression here is unit. unit is the F# way of expressing "this function doesn't really have result" in the type system. Of course, if the function doesn't have a result, in a purely functional language it would be pointless to call it. The only reason to call it would be for some side-effect, and since Haskell doesn't allow side-effects, they use the IO monad to encode the fact the function has an IO producing side-effect into the type system.
F# and other ML-based languages do allow side-effects like IO, so they have the unit type to represent functions that only do side-effects, like printing. When designing your application, you will generally want to avoid having unit-returning functions except for things like logging or printing. If you feel so inclined, you can even use F#'s moand-ish feature, Computation Expressions, to encapsulate your side-effects for you.
Not to be picky, but there's no language OCaml/F# :-)
To answer for OCaml: OCaml is not a pure functional language. It supports side effects directly through mutability, I/O, and exceptions. In many cases it treats such constructs as expressions with the value (), the single value of type unit.
Expressions of type unit can appear in a sequence separated by ;:
let s = ref 0 in
while !s < 10 do
Printf.printf "%d\n" !s; (* This has type unit *)
incr s (* This has type unit *)
done (* The while as a whole has type unit *)
Update
More specifically, ; ignores the value of the first expression and returns the value of the second expression. The first expression should have type unit but this isn't absolutely required.
# print_endline "hello"; 44 ;;
hello
- : int = 44
# 43 ; 44 ;;
Warning 10: this expression should have type unit.
- : int = 44
The ; operator is right associative, so you can write a ;-separated sequence of expressions without extra parentheses. It has the value of the last (rightmost) expression.
To answer the question we need to define what is an expression and what is a statement.
Distinction between expressions and statements
In layman terms, an expression is something that evaluates (reduces) to a value. It is basically something, that may occur on the right-hand side of the assignment operator. Contrary, a statement is some directive that doesn't produce directly a value.
For example, in Python, the ternary operator builds expressions, e.g.,
'odd' if x % 2 else 'even'
is an expression, so you can assign it to a variable, print, etc
While the following is a statement:
if x % 2:
'odd'
else:
'even'
It is not reduced to a value by Python, it couldn't be printed, assigned to a value, etc.
So far we were focusing more on the semantical differences between expressions and statements. But for a casual user, they are more noticeable on the syntactic level. I.e., there are places where a statement is expected and places where expressions are expected. For example, you can put a statement to the right of the assignment operator.
OCaml/Reason/Haskell/F# story
In OCaml, Reason, and F# such constructs as if, while, print etc are expressions. They all evaluate to values and can occur on the right-hand side of the assignment operator. So it looks like that there is no distinction between statements and expressions. Indeed, there are no statements in OCaml grammar at all. I believe, that F# and Reason are also not using word statement to exclude confusion. However, there are syntactic forms that are not expressions, for example:
open Core_kernel
it is not an expression, definitely, and
type students = student list
is not an expression.
So what is that? In the OCaml parlance, they are called definitions, and they are syntactic constructs that can appear in the module on the, so called, top-level. For example, in OCaml, there are value definitions, that look like this
let harry = student "Harry"
let larry = student "Larry"
let group = [harry; larry]
Every line above is a definition. And every line contains an expression on the right-hand side of the = symbol. In OCaml there is also a let expression, that has form let <v> = <exp> in <exp> that should not be confused with the top-level let definition.
Roughly the same is true for F# and Reason. It is also true for Haskell, that has a distinction between expressions and declarations. It actually should be true to probably every real-world language (i.e., excluding brainfuck and other toy languages).
Summary
So, all these languages have syntactic forms that are not expressions. They are not called statements per se, but we can treat them as statements. So there is a distinction between statements and expressions. The main difference from common imperative languages is that some well-known statements (e.g., if, while, for) are expressions in OCaml/F#/Reason/Haskell, and this is why people commonly say that there is no distinction between expressions and statements.

haskell implementation of a sequence

I just started Haskell and I'm struggling!!!
So I need to create a list om Haskell that has the formula
F(n) = (F(n-1)+F(n-2)) * F(n-3)/F(n-4)
and I have F(0) =1, F(1)=1,F(2)=1,F(3)=1
So I thought of initializing the first 4 elements of the list and then have a create a recursive function that runs for n>4 and appends the values to the list.
My code looks like this
let F=[1,1,1,1]
fib' n F
| n<4="less than 4"
|otherwise = (F(n-1)+F(n-2))*F(n-3)/F(n-4) : fib (n-1) F
My code looks conceptually right to me(not sure though), but I get an incorrect indentation error when i compile it. And am I allowed to initialize the elements of the list in the way that I have?
First off, variables in Haskell have to be lower case. Secondly, Haskell doesn't let you mix integers and fractions so freely as you may be used to from untyped or barely-typed languages. If you want to convert from an Int or an Integer to, say, a Double, you'll need to use fromIntegral. Thirdly, you can't stick a string in a context where you need a number. Fourthly, you may or may not have an indentation problem—be sure not to use tabs in your Haskell files, and to use the GHC option -fwarn-tabs to be sure.
Now we get to the heart of the matter: you're going about this all somewhat wrong. I'm going to give you a hint instead of a full answer:
thesequence = 1 : 1 : 1 : 1 : -- Something goes here that *uses* thesequence

meaning of Alloy predicate in relational join

Consider the following simple variant of the Address Book example
sig Name, Addr {}
sig Book { addr : Name -> Addr } // no lone on Addr
pred show(b:Book) { some n : Name | #addr[b,n] > 1 }
run show for exactly 2 Book, exactly 2 Addr, exactly 2 Name
In some model instances, I can get the following results in the evaluator
all b:Book | show[b]
--> yields false
some b:Book | show[b]
--> yields true
show[Book]
--> yields true
If show was a relation, then one might expect to get an answer like: { true, false }. Given that it is a predicate, a single Boolean value is returned. I would have expected show[Book] to be a shorthand for the universally quantified expression above it. Instead, it seems to be using existential quantification to fold the results. Anyone know what might be the rational for this, or have another explanation for the meaning of show[Book]?
(I'm not sure I have the correct words for this, so bear with me if this seems fuzzy.)
Bear in mind that all expressions in Alloy that denote individuals denote sets of individuals, and that there is no distinction available in the language between 'individual X' and 'the singleton set whose member is the individual X'. ([Later addendum:] In the terms more usually used: the general rule in Alloy's logic is that all values are relations. Binary relations are sets of pairs, n-ary relations sets of n-tuples, sets are unary relations, and scalars are singleton sets. See the discussion in sec. 3.2.2 of Software Abstractions, or the slide "Everything's a relation" in the Alloy Analyzer 4 tutorial by Greg Dennis and Rob Seater.)
Given the declaration you give of the 'show' predicate, it's easy to expect that the argument of 'show' should be a single Book -- or more correctly, a singleton set of Book --, and then to expect further that if the argument is not actually a singleton set (as in the expression show[Book] here) then the system will coerce it to being a singleton set, or interpret it with some sort of implicit existential or universal quantification. But in the declaration pred show(b:Book) ..., the expression b:Book just names an object b which will be a set of objects in the signature Book. (To require that b be a singleton set, write pred show(one b: Book) ....) The expression which constitutes the body of show is evaluated for b = Book just as readily as for b = Book$0.
The appearance of existential quantification is a consequence of the way the dot operator at the heart of the expression addr[b,n] (or equivalently n.(b.addr) is defined. Actually, if you experiment you'll find that show[Book] is true whenever there is any name for which the set of all books contains a mapping to two different addresses, even in cases where an existential interpretation would fail. Try adding this to your model, for example:
pred hmmmm { show[Book] and no b: Book | show[b] }
run hmmmm for exactly 2 Book, exactly 2 Addr, exactly 2 Name

autocasting and type conversion in specman e

Consider the following example in e:
var a : int = -3
var b : int = 3
var c : uint = min(a,b); print c
c = 3
var d : int = min(a,b); print d
d = -3
The arguments inside min() are autocasted to the type of the result expression.
My questions are:
Are there other programming languages that use type autocasting, how do they treat functions like min() and max()?
Is this behavior logical? I mean this definition is not consistent with the following possible definition of min:
a < b ? a : b
thanks
There are many languages that do type autocasting and many that will not. I should say upfront that I don't think it's a very good idea, and I prefer a more principled behavior in my language but some people prefer the convenience and lack of verbosity of autocasting.
Perl
Perl is an example of a language that does type autocasting and here's a really fun example that shows when this can be quite confusing.
print "bob" eq "bob";
print "nancy" eq "nancy";
print "bob" == "bob";
print "nancy" == "nancy";
The above program prints 1 (for true) three times, not four. Why not the forth? Well, "nancy" is not == "nancy". Why not? Because == is the numerical equality operator. eq is for string equality. The strings are being compared as you might thing in eq but in == they are being converted to number automatically. What number is "bob" equally to? Zero of course. Any string that doesn't have a number as its prefix is interpreted as zero. For this reason "bob" == "chris" is true. Why isn't "nancy" == "nancy"? Why isn't "nancy" zero? Because that is read as "nan" for "not a number". NaN is not equal to another NaN. I, personally, find this confusing.
Javascript
Javascript is another example of a language that will do type autocasting.
'5' - 3
What's the result of that expression? 2! Very good.
'5' + 3
What's the result of that one? 8? Wrong! It's '53'.
Confused? Good. Wow Javascript, Such Good Conventions, Much Sense. It's a series of really funny Javascript evaluations based on automatic casting of types.
Why would anyone do this!?
After seeing some carefully selected horror stories you might be asking yourself why people who are intelligent enough to invent two of the most popular programming languages in the entire world would do something so silly. I don't like type autocasting but to be fair, there is an argument for it. It's not purely a bug. Consider the following Haskell expression:
length [1,2,3,4] / 2
What does this equal? 2? 2.0? Nope! It doesn't compile due to a type error. length returns an Int and you can't divide that. You must explicitly cast the length to a fraction by calling fromIntegral in order for this to work.
fromIntegral (length [1,2,3,4]) / 2
That can definitely get quite annoying if you're doing a lot of math with integers and floats moving about in your program. But I would greatly prefer that to having to understand why nancy isn't equal to nancy but chris is, in fact, equal to bob.
Happy medium?
Scheme only have one number type. It automatically converts floats and fractions and ints happy and treats them just as you'd expect. It will allow you to divide the length of a list without explicit casting because it knows what you mean. But no, it will never secretly convert a string to a number. Strings aren't numbers. That's just silly. ;)
Your example
As for your example, it's hard to say it is or is not logical. Confusing, yes. I mean you're here on stack overflow aren't you? The reason you're getting 3 I think is either -3 is being interpreted, like Ross said, as a unit in 2's compliment and is a much higher number or because the result of the min is -3 and then it's getting turned into an unsigned int by dropping the negative. The problem is that you asked it for asked it to put the result into an unsigned int but the result is negative. So I would say that what it did is logical in the context of type autocasting, but that type autocasting is confusing. Presumably, you're being saved from having to do explicit type casting all over the place and paying for it with weird behavior like this on occasion.

When are guard expressions appropriate?

Here is an example I wrote that uses if-else branches and guard expressions. When is one more appropriate over the other? The main reason I want to know this is because languages typically have a idiomatic way of doing things.
test1 a b =
if mod b 3 ≡ 0 then a + b
else if mod b 5 ≡ 0 then a + b
else a
test2 a b
| mod b 3 ≡ 0 = a + b
| mod b 5 ≡ 0 = a + b
| otherwise = a
The example you give is a very good demonstration of how guards are better.
With the guards, you have a very simple and readable list of conditions and results — very close to how the function would be written by a mathematician.
With if, on the other hand, you have a somewhat complicated (essentially O(n2) reading difficulty) structure of nested expressions with keywords thrown in at irregular intervals.
For simple cases, it's basically a toss-up between if and guards — if might even be more readable in some very simple cases because it's easier to write on a single line. For more complicated logic, though, guards are a much better way of expressing the same idea.
I always thought it was a matter of preference. Personally, I prefer the second one, I think that the if-elses give a more imperative feel than the guards, and I find the guards easier to read.

Resources