Exception on ACCEPT_TAC after THEN in HOL - sml

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]);

Related

View Proof Steps From Tactic Application

I have spent some time constructing "forward proofs" using the theorem library in HOL. I am now hoping to move to applying tactics to make "backward proofs".
I am wondering if there is a way to, after a tactic has been applied, to view the list of theorems that the tactic applied, i.e., to reconstruct the forward proof in detail. This is mostly to help me understand how tactices work.
For example:
> g `x = 5 ==> 2*x = 10`;
val it = ...
> e (rw[]);
OK...
.
.
.
|- x = 5 ==> 2 * x = 10: proof
>
>
> list_steps(); (* or something similar? *)
REWRITE_RULE [...] t1
REWRITE_RULE [MULT] t2
REWRITE_RULE [MULT_ZERO] t3...
etc.
Thank you!

Theorem proving from first principles using SML with HOL inference rules

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;

How should I calculate p times of f(x)?

I want to calculate f(..f(x)) p times. The following is my code.
let rec function f x p = if p = 0 then x else function f (f x) p-1;;
I wonder how I should make it right.
This is very close, but your code has syntax errors that are going to make it hard to make progress. I think the main problem is that you're using function as an identifier, but it is a keyword in OCaml. If you change to myfun, things should start working quite a bit better.
You also need to watch your precedences. The following code:
f a b-1
is parsed like this:
(f a b) - 1
not like this:
f a (b - 1)
You need to write the parentheses explicitly to get this second parse.
You can define a recursive function ch to apply a function f many times (Church numeral??) as follows:
let rec ch f p x = if p = 0 then x else f (ch f (p-1) x);;
The problems in your original code are that:
need to name the function as something, such as ch here.
need to call the same function ch to get the recursion going as shown above. In your original code, there is no recursion.
Example
let p1 x = x + 1 ;;
ch p1 3 1 ;;
this will give you
- : int = 3
as intended.

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 ();;

Can't get flatten of Try into a for comprehension

This is a combination of a stylistic question, and my attempts to broaden my Scala understanding.
I've got a list containing Future's, I want to compute the values of the futures, transform into Option's, and flatten the list using a for comprehension:
import scala.util.Try
import scala.concurrent._
import ExecutionContext.Implicits.global
val l= List(Future.successful(1),Future.failed(new IllegalArgumentException))
implicit def try2Traversible[A](xo: Try[A]): Iterable[A] = xo.toOption.toList
val res = for{f <- l; v <- f.value} yield v
scala> res: List[scala.util.Try[Int]] = List(Success(1), Failure(java.lang.IllegalArgumentException))
res.flatten
res16: List[Int] = List(1)
What I want to do is get the flatten stage into the for comprehension, anyone got any suggestions?
Doing this is incorrect:
for{f <- l; v <- f.value} yield v
It appears to work in your case only because the futures are already fulfiled, which is why their value member is defined.
However in the general case they might not yet be fulfilled when you execute the for comprehension, and thus value will return None
(despite the fact that at some point they will eventually be fulfilled).
By example, try this in the REPL:
val f1 = Future{
Thread.sleep(3000) // Just a test to illustrate, never do this!
1
}
val f2 = Future{
Thread.sleep(3000) // Just a test to illustrate, never do this!
throw new IllegalArgumentException
}
val l = List( f1, f2 )
for{f <- l; v <- f.value} yield v
The result is an empty list, because none of the futures in l is fulfilled yet. Then wait a bit (at most 3 seconds) and reexecute the for comprehension (the last line), and you will get a non empty list because the futures have finally been fulfilled.
To fix this, you will have to either block (that is, wait for all the futures to be fulfiled) using scala.concurrent.Await, or stay in the asynchronous world by using something like Future.map or Future.flatMap.
By example, if you want to block, you could do:
Await.result( Future.sequence( l ), duration.Duration.Inf )
Await.result waits for the result of the future, allowing to go from the asynchronous world to the synchronous world. The result of the above is a List[Int]
The problem now is that you lose the failure cases (the result is not List[Try[Int]] as you wanted), and will actually rethrow the first exception.
To fix this, you can use this helper method that I posted in another answer: https://stackoverflow.com/a/15776974/1632462
Using it, you can do:
Await.result( Future.sequence( l map mapValue ), duration.Duration.Inf )
This will wait until all the futures are fulfiled (either with a correct value, or with an error) and return the expected List[Try[Int]]
The idea is to traverse to Try object as if it were an Option (i.e. a 0 or 1 element collection) within the for-comprehension itself.
For this traversal to work there has to be a conversion from the Try type to the Option type.
This should work:
implicit def try2option[A](xo: Try[A]) = xo.toOption
val res = for (f <- l; t <- f.value; x <- t) yield x
You should keep a Future around your final result to retain the asynchronous nature of the computation.
The nice way to do this (and obtain a Future[List[Int]]) would be (probably what you tried):
for {
f <- l // Extract individual future
v <- f // Extract value from future
} yield v
Unfortunately this translates to:
l.flatMap(f => f.map(v => v))
Which does not work, because Future does not inherit GenTraversableOnce (and probably shouldn't), but List needs this trait for its flatMap.
However, we can do this manually:
val res = l.foldRight(Future.successful(List.empty[Int])) {
case (x,xs) => xs.flatMap(vxs => x.map(vx => vx :: vxs))
}
We can use Future.sequence to do that:
Future.sequence(l)
This will return a Future[List[Int]] which only completes when all futures are completed and will contain all values of the futures that completed successfully.