Non-total functions are treated as constants at the type level? - typechecking

In Type-Driven Development with Idris, ch 6, he says
Type-level functions exist at compile time only ...
Only functions that are total will be evaluated at the type level. A function that isn't total may not terminate, or may not cover all possible inputs. Therefore, to ensure that type-checking itself terminates, functions that are not total are treated as constants at the type level, and don't evaluate further.
I'm having difficulty understanding what the second bullet point means.
How could the type checker claim the code type checks if there's a function that isn't total in its signature? Wouldn't there by definition be some inputs for which the type isn't defined?
When he says constant, does he mean in the same sense as in the docs, like
one: Nat
one = 1
is a constant? If so, how could that enable the type checker to complete its job?
If a type-level function exists at compile time only, does it ever get evaluated if it's not total? If not, what purpose does it serve?

Partial type-level functions are treated as constants in the Skolem sense: invocations of a partial function f remain f with no further meaning.
Let's see an example. Here f is a partial predecessor function:
f : Nat -> Nat
f (S x) = x
If we then try to use it in a type, it will not reduce, even though f 3 would reduce to 2:
bad : f 3 = 2
bad = Refl
When checking right hand side of bad with expected type
f 3 = 2
Type mismatch between
2 = 2 (Type of Refl)
and
f 3 = 2 (Expected type)
So f is an atomic constant here, standing only for itself. Of course, because it does stand for itself, the following still typechecks:
good : f 3 = f 3
good = Refl

Related

Recursive formula for recurrence that takes 2 arguments

I can create a recursive formula from recurrences where it only passes down one argument (something like $T(n/2)$). However, for a case like this where the value of $u$ and $v$ are different, how do I put them together? This is the problem:
The call to recursive function RecursiveFunction(n, n) for some n > 2
RecursiveFunction(a, b)
if a >= 2 and b >= 2
u=a/2
v=b-1
RecursiveFunction(u, v)
The end goal is to find the tight asymptotic bounds for the worst-case running time, but I just need a formula to start first.
There are in fact two different answers to this, depending on the relative sizes of a and b.
The function can be written as follows:
Where C is some constant work done per call (if statement, pushing u, v onto the call stack etc.). Since the two variables evolve independently, we can analyse their evolution separately.
a - consider the following function:
Expanding the iterative case by m times:
The stopping condition a < 2 is such that:
b - as before:
The complexity of T(a, b) thus depends on which variable reaches its stopping condition first, i.e. the smallest between m and n:

Isabelle function to find the longest sequence of members of a relation

I have a relation R :: w => w => bool that is both transitive an irreflexive.
I have the axiom Ax1: "finite {x::w. True}". Therefore, for each x there is always a longest sequence of wn R ... R w2 R w1 R x.
I need a function F:: w => nat, that -for a given x - gives back the "lenght" of this sequence (or 0 if there is no y such that xRy). How would I go about building one in isabelle.
Also: Is Ax1 a good way to axiomatize the "finiteness of type w" or is there a better one?
First of all, a more idiomatic way of writing {x::w. True} is UNIV :: w set. I suggest writing finite (UNIV :: w set), or possibly using the finite type class, although that might make your theorem more difficult to apply because you need a finite instance for your type. I think it's not really necessary or helpful for your use case.
I then suggest the following approach:
Define an inductive predicate (using inductive) on lists of type w list stating that the first element is x and for each two successive list elements y and z, R y z holds, i.e. the list is an ascending chain w.r.t. R.
Show that any list that is such a chain must have distinct elements (cf. distinct :: 'a list ⇒ bool).
Show that there are finitely many distinct lists over a finite set.
Use the Max operator to find the biggest n such that there exists a list of length n that is an ascending chain w.r.t. R. That this works should be easy since there is at least one such chain, and you've already shown that there are only finitely many chains.

Why is the function addpos defined this way?

The following is the definition of the function addpos which defines addtition of a natural number to an integer. What is puzzling is the fact that here when n is matched with 0, addpos x2 0 gives succZ x2. Why cant it be just x2? Please explain.
Fixpoint addpos (x2 : Z) (n : nat) {struct n} : Z :=
match n with
| O ⇒ succZ x2
| S n0 ⇒ succZ (addpos x2 n0)
end.
I think that, given the name of the function, it is likely that this is intentional behavior. addpos means that we are adding a positive number; if we take "positive" to mean "strictly positive" (as, for instance, it is the case for the positive type in the standard library), then we see that the function is just using an element n : nat to represent the strictly positive number S n.
Why cant it be just x2?
It probably should be. Where did you get this definition from? I don't have succZ in my Coq install, so I had to change that to Z.succ. Then Eval compute in (addpos 0 0) yields 1%Z, for example. Either the definition is wrong, or it is intended to add one more than n.
EDIT: Another answer suggests that it may indeed have been intended to add S n, and the definition accepts n as an encoding for S n. I think such an encoding should be made explicit, since it is easy to do so. For example, by defining a new type for positive integers with a single OnePlus constructor with a nat parameter.

Prolog =:= operator

There are some special operators in Prolog, one of them is is, however, recently I came across the =:= operator and have no idea how it works.
Can someone explain what this operator does, and also where can I find a predefined list of such special operators and what they do?
I think the above answer deserves a few words of explanation here nevertheless.
A short note in advance: Arithmetic expressions in Prolog are just terms ("Everything is a term in Prolog"), which are not evaluated automatically. (If you have a Lisp background, think of quoted lists). So 3 + 4 is just the same as +(3,4), which does nothing on its own. It is the responsibility of individual predicates to evaluate those terms.
Several built-in predicates do implicit evaluation, among them the arithmetic comparsion operators like =:= and is. While =:= evaluates both arguments and compares the result, is accepts and evaluates only its right argument as an arithmetic expression.
The left argument has to be an atom, either a numeric constant (which is then compared to the result of the evaluation of the right operand), or a variable. If it is a bound variable, its value has to be numeric and is compared to the right operand as in the former case. If it is an unbound variable, the result of the evaluation of the right operand is bound to that variable. is is often used in this latter case, to bind variables.
To pick up on an example from the above linked Prolog Dictionary: To test if a number N is even, you could use both operators:
0 is N mod 2 % true if N is even
0 =:= N mod 2 % dito
But if you want to capture the result of the operation you can only use the first variant. If X is unbound, then:
X is N mod 2 % X will be 0 if N is even
X =:= N mod 2 % !will bomb with argument/instantiation error!
Rule of thumb: If you just need arithmetic comparison, use =:=. If you want to capture the result of an evaluation, use is.
?- 2+3 =:= 6-1.
true.
?- 2+3 is 6-1.
false.
Also please see docs http://www.swi-prolog.org/pldoc/man?predicate=is/2
Complementing the existing answers, I would like to state a few additional points:
An operator is an operator
First of all, the operator =:= is, as the name indicates, an operator. In Prolog, we can use the predicate current_op/3 to learn more about operators. For example:
?- current_op(Prec, Type, =:=).
Prec = 700,
Type = xfx.
This means that the operator =:= has precedence 700 and is of type xfx. This means that it is a binary infix operator.
This means that you can, if you want, write a term like =:=(X, Y) equivalently as X =:= Y. In both cases, the functor of the term is =:=, and the arity of the term is 2. You can use write_canonical/1 to verify this:
?- write_canonical(a =:= b).
=:=(a,b)
A predicate is not an operator
So far, so good! This has all been a purely syntactical feature. However, what you are actually asking about is the predicate (=:=)/2, whose name is =:= and which takes 2 arguments.
As others have already explained, the predicate (=:=)/2 denotes arithmetic equality of two arithmetic expressions. It is true iff its arguments evaluate to the same number.
For example, let us try the most general query, by which we ask for any solution whatsoever, using variables as arguments:
?- X =:= Y.
ERROR: Arguments are not sufficiently instantiated
Hence, this predicate is not a true relation, since we cannot use it for generating results! This is a quite severe drawback of this predicate, clashing with what you commonly call "declarative programming".
The predicate only works in the very specific situation that both arguments are fully instantiated. For example:
?- 1 + 2 =:= 3.
true.
We call such predicates moded because they can only be used in particular modes of usage. For the vast majority of beginners, moded predicates are a nightmare to use, because they require you to think about your programs procedurally, which is quite hard at first and remains hard also later. Also, moded predicates severely limit the generality of your programs, because you cannot use them on all directions in which you could use pure predicates.
Constraints are a more general alternative
Prolog also provides much more general arithmetic predicates in the form of arithmetic constraints.
For example, in the case of integers, try your Prolog system's CLP(FD) constraints. One of the most important CLP(FD) constraints denotes arithmetic equality and is called (#=)/2. In complete analogy to (=:=)/2, the operator (#=)/2 is also defined as an infix operator, and so you can write for example:
| ?- 1 + 2 #= 3.
yes
I am using GNU Prolog as one particular example, and many other Prolog systems also provide CLP(FD) implementations.
A major attraction of constraints is found in their generality. For example, in contrast to (=:=)/2, we get with the predicate (#=)/2:
| ?- X + 2 #= 3.
X = 1
| ?- 1 + Y #= 3.
Y = 2
And we can even ask the most general query:
| ?- X #= Y.
X = _#0(0..268435455)
Y = _#0(0..268435455)
Note how naturally these predicates blend into Prolog and act as relations between integer expressions that can be queried in all directions.
Depending on the domain of interest, my recommendition is to use CLP(FD), CLP(Q), CLP(B) etc. instead of using more low-level arithmetic predicates.
Also see clpfd, clpq and clpb for more information.
Coincidentally, the operator =:= is used by CLP(B) with a completely different meaning:
?- sat(A =:= B+1).
A = 1,
sat(B=:=B).
This shows that you must distinguish between operators and predicates. In the above case, the predicate sat/1 has interpreted the given expression as a propositional formula, and in this context, =:= denotes equality of Boolean expressions.
I found my own answer, http://www.cse.unsw.edu.au/~billw/prologdict.html
Its an ISO core standard predicate operator, which cannot be bootstrapped from unification (=)/2 or syntactic equality (==)/2. It is defined in section 8.7 Arithmetic Comparison. And it basically behaves as follows:
E =:= F :-
X is E,
Y is F,
arithmetic_compare(=, X, Y).
So both the left hand side (LHS) and right hand side (RHS) must be arithmetic expressions that are evaluted before they are compared. Arithmetic comparison can compare across numeric types. So we have:
GNU Prolog 1.4.5 (64 bits)
?- 0 = 0.0.
no
?- 0 == 0.0
no
?- 0 =:= 0.0.
yes
From Erlang I think it could be good to annotate that as syntax are mostly look alike to Prolog.
=:= expression is meaning of exactly equal.
such as in JavaScript you can use === to also see if the type of the variables are same.
Basically it's same logic but =:= is used in functional languages as Prolog, Erlang.
Not much information but hope it could help in some way.
=:= is a comparison operator.A1 =:= A2 succeeds if values of expressions A1 and A2 are equal.
A1 == A2 succeeds if terms A1 and A2 are identical;

Why is this J function not running?

I am attempting to learn J and the book I am using says this is the proper way to define a monadic function
function =: 3:0
function statements
so I followed this format and wrote the folding code. Can you tell me why this is throwing a syntax error when I try to call it with input but if I just call p it returns 3
h=:>:#i.#<.#-: :[: NB. gets all integers less than half of the input :[: forces error if used dyadicly
d=:(0&=|)~ h :[: NB. gets list where if one is set that index from h was a factor of the input y :[: forces error if used dyadicly
p=: 3:0 NB. tells us p is a monadic function
t =: d y
a =: i. 1
while. 1<#t
if. t~:0
a =: a, #t
end.
t=: _1 }. t NB. found first mistake wrong bracket but fixing that doesn't fix it
end.
a*1
)
NB. p gets a list of all integers that are factors of y
p 4
| syntax error
| p 4
p
3
NB. h and d run fine
h 4
1 2
h 7
1 2 3
d 7
1 0 0
d 4
1 1
Firstly, 3:0 parses like (3:) (0), i.e. the monad "3:" applied to the noun "0". That's not what you want; for definitions, you want to use the dyad ":", so you need to separate it from the 3 with a space.
Secondly, you should use =. instead of =: inside the definition, as t and a are local variables.
Several parts can be simplified:
d =: 0 = h | [ NB. does h y divide y
p =: d # h NB. select d y from h y
Same functionality as before, but clearer and faster.
I figured it out sort of I get a stack error instead of a syntax error with monad define instead of using 3:0. I still have to work out a few kinks but I'm making progress.
h =:>:#i.#<.#-:
d =:(0&=#|)~ h
p =: monad define
t =: d y
a =: i.0
while. 1<#t do.
if. {:t~:0 do.
a=:a, #t
end.
t=: _1 }. t
end.
a
)
my latest attempt is a good deal close getting a value error now. Still not sure why its failing but I'll get it soon. I figured it out I was forgetting the required do. after the conditionals adding them fixes everything.

Resources