Theorem proving from first principles using SML with HOL inference rules - sml

I am trying to prove the theorem [] |- p /\ q <=> q /\ p :thm using SML with HOL Inference Rules. Here's the SML code:
val thm1 = ASSUME ``p:bool /\ q:bool``;
val thm2 = ASSUME ``p:bool``;
val thm3 = ASSUME ``q:bool``;
val thm4 = CONJ thm2 thm3;
val thm5 = CONJ thm3 thm2;
val thm6 = DISCH ``(q:bool/\p:bool)`` thm4;
val thm7 = DISCH ``(p:bool/\q:bool)`` thm5;
val thm8 = IMP_ANTISYM_RULE thm6 thm7;
The result of the above code produces :
val thm8 = [(p :bool), (q :bool)] |- (q :bool) /\ (p :bool) <=> p /\ q: thm
What am I doing wrong?

The problem with your final theorem is that you still have p and q as assumptions, introduced via thm2 and thm3, whereas you can and should obtain them from thm1.
The first theorem you need is something like p /\ q ==> p. I found the appropriate rule by skimming through the description (sec. 2.3.24). It's called CONJUNCT1.
Using it, we can obtain p as a theorem from thm1:
val thmp = CONJUNCT1 thm1;
The same idea works to get q as a theorem from thm1:
val thmq = CONJUNCT2 thm1;
And then you can apply your idea for thm5:
val thm5 = CONJ thmq thmp;
The important thing here is that we do not use p derived from p (thm2) and q derived from q (thm3) but rather p derived from p /\ q and q derived from p /\ q (setting show_assumes := true; may help to see this more clearly).
Finally, we apply your idea for thm7:
val thm7 = DISCH ``p /\ q`` thm5;
to obtain the first half of the desired result, but with no extraneous assumptions.
The second half is obtained in a similar way:
val thm9 = ASSUME (``q /\ p``);
val thmp2 = CONJUNCT2 thm9;
val thmq2 = CONJUNCT1 thm9;
val thm6 = DISCH ``q /\ p`` (CONJ thmp2 thmq2);
And then your idea for thm8 works perfectly:
val thm8 = IMP_ANTISYM_RULE thm7 thm6;

Related

Simplify a repetitive pattern using monads

I'm actually not sure this is doable with monads or that it should be done with them and I'm looking for a solution rather than solve it with monads if monads are not the solution.
Let's say I have the following code (simplified but the idea is here):
module IM = Map.Make (Int)
let f k v m =
if IM.mem k m then (m, true)
else (IM.add k v m, false)
let a =
let m = IM.empty in
let m, res = f 0 "Zero" m in
if res then
let m, res = f 1 "One" m in
if res then f 2 "Two" m else (m, res)
else (m, res)
I'm repeating multiple times:
let value, boolean = function application to value and other values in
if boolean then another function application to the new value and other values (not the same as the first one)
else the result
This means that these functions don't necessarily have the same type but they all return a a IM.t * bool (a being the same type for every function)
I wondered if it was possible to create an inline operator that would allow me to do it.
I tried something like:
module EqMonad = struct
let ( let* ) (t, res) f2 = if res then f2 t else (t, false)
let return t = t
end
But it'll obviously not work because f2 takes more than one argument but needs to receive t as its last argument.
I guess I could summarize my problem like this:
Is it possible to have monads wrapping variadic functions?
Your solution works (with return corrected to be the monadic return) and is a restricted version of the error monad:
let return x = x, true
let a =
let m = IM.empty in
let* m = f 0 "Zero" m in
let* m = f 1 "One" m in
let* m = f 2 "Two" m in
return m
However, since the control flow never depends on the value of m, this is a sign that it might simpler to use a regular function:
let rec add_first_fresh m l = match l with
| [] -> None
| (k,v):: q ->
if IM.mem k m then add_first_fresh m q
else Some (IM.add k v m)
let a = add_first_fresh IM.empty
[0, "Zero";
1, "One";
2, "Two"
]

Exception on ACCEPT_TAC after THEN in HOL

I am trying to create a theorem named "absorptionRule" by packaging the tactics that are used to prove the goal !(p:bool) (q:bool). (p==>q) ==> p ==> p /\ q. However, I am getting an exception on ACCEPT_TAC. When I execute each tactic one-by-one, everything works fine.
val absorptionRule =
TAC_PROOF(
([],``!(p:bool) (q:bool).(p ==> q) ==> p ==> p /\ q``),
REPEAT STRIP_TAC THEN
ACCEPT_TAC(ASSUME ``p:bool``) THEN
RES_TAC);
The THEN tactical applies the second tactic to all the subgoals produced by the first tactic (source). But ACCEPT_TAC (ASSUME ``p:bool``) only applies to the first subgoal. You do not see any problem when you apply the tactics one-by-one because you never try to apply the ACCEPT_TAC to the second subgoal. The following solution uses THENL instead of THEN.
val g1 = (([], ``!(p:bool) (q:bool). (p ==> q) ==> p ==> p /\ q``) : goal);
val absorptionRule =
TAC_PROOF (g1,
REPEAT STRIP_TAC
THENL [ACCEPT_TAC (ASSUME ``p:bool``), RES_TAC]);

What does function return when "function times zero" in functional programming?

I am stuck with this SML assignment. I am trying to create a compound function (fun compound n f). It's supposed to apply the function f on itself for n times for example, compound 3 f will equal to f(f(f(x))). I got it to work except for case where n is zero. I asked the professor but he won't tell me a direct answer. He tried to give me an hint that "what's function times zero?" I still can't figure that out either. Can stackoverflow figure it out?
Thanks.
My code:
fun compound n f =
if n < 2 then
if n = 0 then fn x => f x else fn x => f x
else fn x => f(compound (n-1) f(x));
example:
val fnc = fn x => x + 1; (* example function to be used *)
compound 5 fnc(10); (* will return 15 which is correct*)
compound 0 fnc(10); (* returns 11, should be 10 *)
Answer:
fun compound n f =
if n < 2 then
if n = 0 then fn x => x else fn x => f x
else fn x => f(compound (n-1) f(x));
I won't give you the final answer because I don't like to upset teachers ;) However, I'll try a derivation that I believe you'll find easy to complete.
Let's start from a very simple case. Let's "reimplement" function application, i.e., let's write a function that takes a function and an argument and apply the first param to the second one:
fun apply f a = f a
Let's use a contrived function, that increments integers, for testing:
- fun inc n = n + 1;
val inc = fn : int -> int
- inc 1;
val it = 2 : int
- apply inc 1;
val it = 2 : int
Now, let's write apply2, a function which takes a function and an argument and applies the param function two times to the argument:
fun apply2 f a = f (f a)
Let's test it with inc:
- apply2 inc 1;
val it = 3 : int
Seems to be working. As you might expect, we'd now implement apply3, apply4 and so on. Let's see some of them at once:
fun apply f a = f a
fun apply2 f a = f (f a)
fun apply3 f a = f (f (f a))
fun apply4 f a = f (f (f (f a)))
It looks like we can rewrite later ones in terms of the earlier ones:
fun apply2 f a = f (apply f a)
fun apply3 f a = f (apply2 f a)
fun apply4 f a = f (apply3 f a)
We can even rewrite apply:
fun apply f a = f (apply0 f a)
Remember the previous definition of apply, they're equivalent:
fun apply f a = f a
So, what should apply0 be?
fun apply0 f a = ...
What is the base case for this algorithm? i.e. at what value of n does the recursion terminate? When it terminated what do you return? Think about what you would want to return if f is not applied to x. In the context of your example, if fnc is applied to 10 zero times, what should be returned?
fun compound n f =
(* If n equals the termination value, then return the base case*)
if n = ?
else fn x => f(compound (n-1) f(x));
There is a pattern here that exists in the base case for recursive algorithms. For example, what is the sum of a list with no elements? Or, what is the length of a list with no elements?

Procedure of executing in OCaml

I have following piece of code:
let p = print_string("finished\n");;
let x0 = ref 0;;
class point =
object
val mutable x = incr x0; !x0
method get_x = x
method move d = x <- x + d
end
;;
print_int(new point#get_x);;
p;;
print_int(new point#get_x);;
p;;
Can't understand why the output is:
finished
12
My expectation is actually like:
1
finished
2
finished
Anyone can tell what's the correct order of executing this piece of code?
The main point of confusion is that your p isn't a function. It's just a value. In particular, it is the value () (known as unit). So when you evaluate p later in your code it has no effect. All the work was done when p was created.
If you want p to act like a function (which is what you seem to want), you should define it like this:
let p () = print_string "finished\n";;
And you should call it like this:
p ();;

warning 10 : this expression should have type unit

I'm writing a program in ocaml containing some loops "for", my problem is that for each of these cycles you receive this message: "warning 10 : this expression should have type unit. "
Example :
let f q p rho=
let x = [] in
if q > p then
for i=0 to rho do
x= q :: x
done;
x;;
this every time I use a cycle "for" ,how can I solve this problem?
There are several problems with your code.
The error is because the for does not return anything, and so the inside of the loop to be purely for side-effect. So it should have unit type. Your use of = does not have unit type, because = is in fact the equality operator, comparing two values, and returning true or false.
So you are using the wrong operator. It appears that you are trying to "assign" to x. But in ML, you cannot assign to "variables", because they are bound to a value when they are defined and cannot change. One way to get mutability, is to use a mutable cell (called a "reference"): you use the ref function to create the mutable cell from an initial value; the ! operator to get its value out; and the := operator to change the value inside.
So for example:
let f q p rho=
let x = ref [] in
if q > p then
for i=0 to rho do
x := q :: !x
done;
!x;;
This kind of loop is probably best expressed using recursion:
let f q p rho=
let rec loop i =
if i > rho then
[]
else
q::(loop (i+1))
in
if q > p then
loop 0
else
[];;
Or we can make it tail recursive:
let f q p rho=
let rec loop i acc =
if i > rho then
acc
else
loop (i+1) (q::acc)
in
if q > p then
loop 0 []
else
[];;