I'm asking your help because I would like to know if it would be possible to allow the definition of potentially infinite fixpoints in Coq, just to check if the current definition eventually produces an output.
I've tried the new Unset Guard Checking command, be what I'd like to disable precisely is the decreasing argument checking (because I actually have the error cannot guess decreasing argument of fix.
I understand that it is a bit of a shame to disable this feature in Coq, but it is just to get a small utility function to check whether the current definition is correct, to make sure that providing then a decreasing argument will work in further development.
Unset Guard Checking does disable the decreasing argument checking.
You may have to explicitly specify the argument which you want the system to assume decreasing using {struct foo} like this example.
Unset Guard Checking.
Fixpoint y {A} (f : A -> A) {struct f} : A := f (y f).
However, if you don't have a strong reason, the better way to define a possibly infinite function is to add an argument to force termination.
Fixpoint y_opt {A} (lim : nat) (f : A -> A) : option A :=
match lim with
| O => None
| S lim' =>
match y_opt lim' f with
| None => None
| Some x => Some (f x)
end
end.
Related
assume I have a function
definition "foo_function x = x+1"
And I have some code which processes functions. For the sake of simplicity, let this code be the identity function id. I want to print an example. I want to print that
id foo_function = foo_function
The printing shall appear in the proof doc and I want it to be checked. How can I best achieve this?
I already tried a few things:
value ‹id foo_function› raises Wellsortedness error ...
value[simp] ‹id foo_function› returns foo_function in the output panel and is quite close to what I'm looking for. But I really want to print id foo_function = foo_function and have this checked. I don't want folks to go to the output panel.
lemma ‹id foo_function = foo_function› by eval is what I'd like to have but it fails with Wellsortedness error: Type 'a ⇒ 'a not of sort equal
lemma ‹id foo_function = foo_function› by(code_simp) fails with Wellsortedness error: Type 'a ⇒ 'a not of sort equal
lemma ‹id foo_function = foo_function› by(normalization) fails with Wellsortedness error: Type 'a ⇒ 'a not of sort equal
I know that the underlying problem is equality of functions, which is absolutely not trivial and I don't expect eval to solve this. Yet, value[simp] ‹id foo_function› displays in the output panel exactly what I want to see, which gives me hope that there is a way to achieve what I'm looking for.
In my simplified example, lemma ‹id foo_function = foo_function› by(simp add: foo_function_def) would work. But for my real problem, there are way too many definitions which need unfolding to make this a pleasant choice. In particular, since I want to print a lot of examples.
Here's one possible solution:
ML‹
fun bar_conv ctxt =
Conv.arg_conv (Conv.arg1_conv (Code_Simp.dynamic_conv ctxt) then_conv Conv.arg_conv (Code_Simp.dynamic_conv ctxt))
fun bar_tac ctxt =
HEADGOAL (CONVERSION (bar_conv ctxt) THEN_ALL_NEW (resolve_tac ctxt #{thms refl}))
›
method_setup bar = ‹Scan.succeed (SIMPLE_METHOD o bar_tac)›
lemma ‹id foo_function = foo_function›
by bar
What does it do?
bar_conv defines a conv (which is a rewriting function) that rewrites both sides of the equation with Code_Simp.dynamic_conv, essentially the same thing that code_simp does, except for ignoring the equality sign. (The outher arg_conv is to dive into the Trueprop that every lemma has.)
bar_tac turns the conv into a tactic, then applies the refl theorem, which discharges the remaining goal of the shape x = x.
method_setup creates an Isar binding for the method.
data Even: Nat -> Type where
EvenZ: Even Z
EvenS: Even n -> Even (n + 2)
total
lemma1: Even Z
lemma1 = EvenZ
-- total
-- lemma2: Even Z
-- lemma2 impossible -- Idris says 'lemma2 is a valid case' and I agree with you
total
lemma3: Even 2
lemma3 = EvenS EvenZ
total
lemma4: Even 2 -> Void
lemma4 x impossible -- what does it work?
total
lemma5: Even 1 -> Void
lemma5 x impossible
I wrote some proofs on Even.
lemma1, lemma2 and lemma3 are ok, but lemma4 looks strange to me.
AFAIK, both lemma3 and lemma4 can not be provable at the same time.
I expected impossible keyword in lemma4 not to work and expected Idris to show me some error messages about the wrong usage of impossible.
Is impossible an unsafe keyword that can be used to assert to type checker?
we have mapOptional from the NICTA course:
mapOptional :: (a -> b) -> Optional a -> Optional b
mapOptional _ Empty = Empty
mapOptional f (Full a) = Full (f a)
When matching f we obviously use that function that was passed, what about the Empty? and what about Full?
There is nothing in Haskell that lets you observe whether the two Emptys are the same Empty or not, and no guarantees about what an implementation must do with that code in that regard.
That said, in GHC, nullary constructors for a given parameterized type are shared across all parameterizations; so there is just one Empty in the whole program, and just one [], and so forth.
They can't be the same Empty, the argument has the type Optional a and the output has the type Optional b. When I try to force some sort of reuse, I will typically use something of the type
mapOptional _ a#Empty = a
This won't compile, and I don't think that's implementation dependent.
This is a derivative question of Existing constants (e.g. constructors) in type class instantiations.
The short question is this: How can I prevent the error that occurs due to free_constructors, so that I can combine the two theories that I include below.
I've been sitting on this for months. The other question helped me move forward (it appears). Thanks to the person who deserves thanks.
The real issue here is about overloading notation, though it looks like I now just have a namespace problem.
At this point, it's not a necessity, just an inconvenience that two theories have to be used. If the system allows, all this will disappear, but I ask anyway to make it possible to get a little extra information.
The big explanation here comes in explaining the motivation, which may lead to getting some extra information. I explain some, then include S1.thy, make a few comments, and then include S2.thy.
Motivation: using syntactic type classes for overloading notation of multiple binary datatypes
The basic idea is that I might have 5 different forms of binary words that have been defined with datatype, and I want to define some binary and hexadecimal notation that's overloaded for all 5 types.
I don't know what all is possible, but the past tells me (by others telling me things) that if I want code generation, then I should use type classes, to get the magic that comes with type classes.
The first theory, S1
Next is the theory S1.thy. What I do is instantiate bool for the type classes zero and one, and then use free_constructors to set up the notation 0 and 1 for use as the bool constructors True and False. It seems to work. This in itself is something I specifically wanted, but didn't know how to do.
I then try to do the same thing with an example datatype, BitA. It doesn't work because constant case_BitA is created when BitA is defined with datatype. It causes a conflict.
Further comments of mine are in the THY.
theory S1
imports Complex_Main
begin
declare[[show_sorts]]
(*---EXAMPLE, NAT 0: IT CAN BE USED AS A CONSTRUCTOR.--------------------*)
fun foo_nat :: "nat => nat" where
"foo_nat 0 = 0"
(*---SETTING UP BOOL TRUE & FALSE AS 0 AND 1.----------------------------*)
(*
I guess it works, because 'free_constructors' was used for 'bool' in
Product_Type.thy, instead of in this theory, like I try to do with 'BitA'.
*)
instantiation bool :: "{zero,one}"
begin
definition "zero_bool = False"
definition "one_bool = True"
instance ..
end
(*Non-constructor pattern error at this point.*)
fun foo1_bool :: "bool => bool" where
"foo1_bool 0 = False"
find_consts name: "case_bool"
free_constructors case_bool for "0::bool" | "1::bool"
by(auto simp add: zero_bool_def one_bool_def)
find_consts name: "case_bool"
(*found 2 constant(s):
Product_Type.bool.case_bool :: "'a∷type => 'a∷type => bool => 'a∷type"
S1.bool.case_bool :: "'a∷type => 'a∷type => bool => 'a∷type" *)
fun foo2_bool :: "bool => bool" where
"foo2_bool 0 = False"
|"foo2_bool 1 = True"
thm foo2_bool.simps
(*---TRYING TO WORK A DATATYPE LIKE I DID WITH BOOL.---------------------*)
(*
There will be 'S1.BitA.case_BitA', so I can't do it here.
*)
datatype BitA = A0 | A1
instantiation BitA :: "{zero,one}"
begin
definition "0 = A0"
definition "1 = A1"
instance ..
end
find_consts name: "case_BitA"
(*---ERROR NEXT: because there's already S1.BitA.case_BitA.---*)
free_constructors case_BitA for "0::BitA" | "1::BitA"
(*ERROR: Duplicate constant declaration "S1.BitA.case_BitA" vs.
"S1.BitA.case_BitA" *)
end
The second theory, S2
It seems that case_BitA is necessary for free_constructors to set things up, and it occurred to me that maybe I could get it to work by using datatype in one theory, and use free_constructors in another theory.
It seems to work. Is there a way I can combine these two theories?
theory S2
imports S1
begin
(*---HERE'S THE WORKAROUND. IT WORKS BECAUSE BitA IS IN S1.THY.----------*)
(*
I end up with 'S1.BitA.case_BitA' and 'S2.BitA.case_BitA'.
*)
declare[[show_sorts]]
find_consts name: "BitA"
free_constructors case_BitA for "0::BitA" | "1::BitA"
unfolding zero_BitA_def one_BitA_def
using BitA.exhaust
by(auto)
find_consts name: "BitA"
fun foo_BitA :: "BitA => BitA" where
"foo_BitA 0 = A0"
|"foo_BitA 1 = A1"
thm foo_BitA.simps
end
The command free_constructors always creates a new constant of the given name for the case expression and names the generated theorems in the same way as datatype does, because datatype internaly calls free_constructors.
Thus, you have to issue the command free_constructors in a context that changes the name space. For example, use a locale:
locale BitA_locale begin
free_constructors case_BitA for "0::BitA" | "1::BitA" ...
end
interpretation BitA!: BitA_locale .
After that, you can use both A0 and A1 as constructors in pattern matching equations and 0 and 1, but you should not mix them in a single equation. Yet, A0 and 0 are still different constants to Isabelle. This means that you may have to manually convert the one into the other during proofs and code generation works only for one of them. You would have to set up the code generator to replace A0 with 0 and A1 with 1 (or vice versa) in the code equations. To that end, you want to declare the equations A0 = 0 and A1 = 1 as [code_unfold], but you also probably want to write your own preprocessor function in ML that replaces A0 and A1 in left-hand sides of code equations, see the code generator tutorial for details.
Note that if BitA was a polymorphic datatype, packages such as BNF and lifting would continue to use the old set of constructors.
Given these problems, I would really go for the manual definition of the type as described in my answer to another question. This saves you a lot of potential issues later on. Also, if you are really only interested in notation, you might want to consider adhoc_overloading. It works perfectly well with code generation and is more flexible than type classes. However, you cannot talk about the overloaded notation abstractly, i.e., every occurrence of the overloaded constant must be disambiguated to a single use case. In terms of proving, this should not be a restriction, as you assume nothing about the overloaded constant. In terms of definitions over the abstract notation, you would have to repeat the overloading there as well (or abstract over the overloaded definitions in a locale and interpret the locale several times).
This is with SBCL 1.0.55 on Debian squeeze. I'm probably missing something obvious, but I'm a beginner, so please bear with me.
CL-USER> (defparameter x 0)
CL-USER> (case x (t 111) )
111
So it looks like case here is matching the variable x with the truth symbol t. This happens with everthing I've tried; this x is just an example. I don't see why this would happen. Since case uses eql for matching, I tried
CL-USER> (eql x t)
NIL
So, eql does not match x and t. What am I missing? Thanks in advance.
Described in the CASE documentation.
otherwise-clause::= ({otherwise | t} form*)
The syntax says that an otherwise clause is either (otherwise form-1 ... form-n) or (t form-1 ... form-n). Note that the syntax says {otherwise | t}. The vertical bar is an OR in a syntax specification. So the marker for an otherwise clause is either otherwise or t.
That means, if your case clause begins with otherwise or t, then we have an otherwise-clause.
In the case construct in Common Lisp, t, used by itself, is equivalent to default in C; that is, it's evaluated if the expression doesn't match any of the other cases. If you want to match the actual symbol t, use (t) instead.