I’m doing my first experiments with codatatype, but I’m stuck rather early. I started with this definition of a branching, possibly infinite tree:
codatatype (lset: 'a) ltree = Node (lnext : "'a ⇒ 'a ltree option")
and some definitions work fine:
primcorec lempty :: "'a ltree"
where "lnext lempty = (λ _ . None)"
primcorec single :: "'a ⇒ 'a ltree"
where "lnext (single x) = (λ _ . None)(x := Some lempty)"
but this does not work:
primcorec many :: "'a ⇒ 'a ltree"
where "lnext (many x) = (λ _ . None)(x := Some (many x))"
as I get the error message
primcorec error:
Invalid map function in "[x ↦ many x]"
I could work around it by writing
primcorec many :: "'a ⇒ 'a ltree"
where "lnext (many x) = (λ x'. if x' = x then Some (many x) else None)"
which makes be believe that primcorec needs to “know something about” the function update operator, similar to how fun needs fundef_cong lemmas and inductive needs mono lemmas. But what exactly?
If the codatatype recurses through other type constructors, then primcorec expects that the recursive calls are properly nested in the map functions of these type constructors. In the example, the recursion goes through the function type and the option type, whose map functions are op o and map_option. Consequently, the recursive call to many should have the form op o (map_option many). Hence, the following definition works:
primcorec many :: "'a ⇒ 'a ltree"
where "lnext (many x) = map_option many ∘ [x ↦ x]"
For convenience, primcorec supports a few more syntactic input formats. In particular, the map function for the function type can be also written using lambda abstractions. Additionally, it supports case distinctions and ifs. This is why your second version is accepted. However, when you look at the generated definition many_def, you will see that it is more complicated than with the explicit map functions.
primcorec does not suport registration of arbitrary functions, so you cannot use fun_upd in the original form. Primitive corecursion is syntactical. Maybe in the future there will be a corecursive counterpart to function.
The map functions are explained in the tutorial on datatypes and in this paper.
Related
Im really new to isabelle, this is my problem
theory MyTheory3
imports Main
begin
(* 3.1) a) define a type natpair, whose elements are pairs of natural numbers.*)
datatype natpair = Natpair "nat × nat"
(*3.1 b)define a function of type natpair ⇒ nat that returns the sum of the elements of a pair of natural
numbers.*)
definition natpair_sum :: "natpair ⇒ nat" where
"Natpair((a::nat) × (b::nat)) = a + b"
end
i get the error
Type unification failed: Clash of types "nat" and "_ set"
Type error in application: incompatible operand type
Operator: (×) :: ??'a set ⇒ ??'b set ⇒ (??'a × ??'b) set Operand: a
:: nat
in addition, can someone show me an example of natpair with a parameterized
constructor
Thanks in advance
youre nuric
Your code has several issues:
Operator (×) is not a constructor for pairs but the Cartesian product of sets; pairs are constructed using the syntax (a, b) or Pair a b.
The definition natpair_sum does not use its name in the equation, that is, the correct syntax is definition natpair_sum :: "natpair ⇒ nat" where "natpair_sum ... = ...".
Pattern matching is not allowed in the left-hand side of a definition; you can use the case construct in the right-hand side of the definition or you can use functions instead.
There is no need to add type annotations for the components of the pair.
As examples, here are two possible definitions for natpair_sum:
definition natpair_sum :: "natpair ⇒ nat" where
"natpair_sum np = (case np of Natpair (a, b) ⇒ a + b)"
fun natpair_sum :: "natpair ⇒ nat" where
"natpair_sum (Natpair (a, b)) = a + b"
As for your last question, I'm not quite sure what you mean by "an example of natpair with a parameterized constructor". Natpair is already a data constructor which takes a pair of nat's as the only parameter.
I am trying to use the export_code tool for the following definition:
definition set_to_list :: "('a×'a) set ⇒ ('a×'a) list"
where "set_to_list A = (SOME L. set L = A)"
This is not working due to missing code equations for Eps. Now I discovered that there is also a definition:
definition sorted_list_of_set :: "'a set ⇒ 'a list" where
"sorted_list_of_set = folding.F insort []"
However, I am not capable of asserting that ('a ×'a) is a linear order (which would be fine for me, e.g. first comparing the first element and then the second). Can someone help me to either fix my own definition or using the existing one?
To use sorted_list_of_set you can implement the type class linorder for product types:
instantiation prod :: (linorder,linorder) linorder begin
definition "less_eq_prod ≡ λ(x1,x2) (y1,y2). x1<y1 ∨ x1=y1 ∧ x2≤y2"
definition "less_prod ≡ λ(x1,x2) (y1,y2). x1<y1 ∨ x1=y1 ∧ x2<y2"
instance by standard (auto simp add: less_eq_prod_def less_prod_def)
end
You can also import "HOL-Library.Product_Lexorder" from the standard library, which includes a similar definition.
Then you can define set_to_list if you restrict the type parameter to implement linorder:
definition set_to_list :: "('a::linorder×'a) set ⇒ ('a×'a) list"
where "set_to_list A = sorted_list_of_set A"
I need to defined an extended bool type (ebool = bool ∪ {⊥}) and a set of operations for the type (conjunction, etc.).
Here is the theory:
theory EboolTest
imports Main "~~/src/HOL/Library/Adhoc_Overloading"
begin
notation
bot ("⊥")
declare [[coercion_enabled]]
typedef ebool = "UNIV :: bool option set" ..
definition ebool :: "bool ⇒ ebool" where
"ebool b = Abs_ebool (Some b)"
declare [[coercion "ebool :: bool ⇒ ebool"]]
instantiation ebool :: bot
begin
definition "⊥ ≡ Abs_ebool None"
instance ..
end
free_constructors case_ebool for
ebool
| "⊥ :: ebool"
apply (metis Rep_ebool_inverse bot_ebool_def ebool_def not_Some_eq)
apply (smt Abs_ebool_inverse ebool_def iso_tuple_UNIV_I option.inject)
by (simp add: Abs_ebool_inject bot_ebool_def ebool_def)
lemmas ebool2_cases = ebool.exhaust[case_product ebool.exhaust]
lemmas ebool3_cases = ebool.exhaust[case_product ebool.exhaust ebool.exhaust]
fun ebool_and :: "ebool ⇒ ebool ⇒ ebool" (infixr "∧" 35) where
"ebool_and a b = ebool (HOL.conj a b)"
| "ebool_and False _ = False"
| "ebool_and _ False = False"
| "ebool_and ⊥ _ = ⊥"
| "ebool_and _ ⊥ = ⊥"
no_notation HOL.conj (infixr "∧" 35)
consts "(∧)" :: "'a ⇒ 'a ⇒ 'a"
adhoc_overloading "(∧)" HOL.conj
adhoc_overloading "(∧)" ebool_and
end
The following works fine:
value "True ∧ (False::ebool)"
value "True ∧ ⊥"
But the following returns ebool, but I expect to see bool:
value "True ∧ False"
It seems my approach is bad. Could you suggest a better approach? Maybe I it's not good to overload standard operations at all?
First of all, I'm a little surprised that this:
consts "(∧)" :: "'a ⇒ 'a ⇒ 'a"
works at all. It sounds like a bug, because the (...) notation is reserved for the system. (To be fair, it does print a warning, and unless you know exactly what you're doing, it's unwise to ignore them.)
But to circle back to your actual problem, I don't think you should use adhoc_overloading to overload syntax that would otherwise be provided by Main.
There are alternatives. For example, you could use a bold version. This is used in this theory.
Or you could use another symbol, like &&.
As an addendum: I believe there might be weird interactions between coercions and adhoc overloading. Both tools are fine by themselves, but watch out if they interact with each other.
I can merge two finite maps as follows:
value "fmadd
(fmap_of_list [(1::nat,2::nat)])
(fmap_of_list [(2::nat,3::nat)])"
But when I try to merge a set of maps:
value "ffold fmadd fmempty {|
fmap_of_list [(1::nat,2::nat)],
fmap_of_list [(2::nat,3::nat)]|}"
I get the following error:
Wellsortedness error:
Type nat ⇀⇩f nat not of sort finite
No type arity fmap :: finite
According to definition of fmap, it's domain is finite:
typedef ('a, 'b) fmap = "{m. finite (dom m)} :: ('a ⇀ 'b) set"
morphisms fmlookup Abs_fmap
proof
show "Map.empty ∈ {m. finite (dom m)}"
by auto
qed
But why fmap is not finite?
To answer your immediate question:
But why fmap is not finite?
Every fmap has a finite domain, but it is not necessarily the case that there are only finitely many values of type ('a, 'b) fmap. For example, there are infinitely many finitely-sized mappings from nat to nat.
The problem you're observing is deeper than that: I believe there is no proper code setup for ffold. If I try to compute
ffold funion fempty {|
fset_of_list [(1::nat,2::nat)],
fset_of_list [(2::nat,3::nat)]|}
... the error message is similar. For now, I would recommend rewriting it as fold on lists:
fold fmadd [
fmap_of_list [(1::nat,2::nat)],
fmap_of_list [(2::nat,3::nat)]] fmempty
It's not the same but it might be useful for your application.
I am working with limits and I am unable to prove the following
definition func :: "real ⇒ real"
where "func = real"
lemma "(λh. (func (x+h))) -- 0 --> (func (x))"
unfolding func_def
apply (auto intro!: tendsto_eq_intros)
However if I replace the definition of func to
definition func :: "real ⇒ real"
where "func x = x"
the lemma is solved.
How can I solve this lemma when working with generic definitions?
I believe, here the problem is that the function real has just a generic (overloaded) syntax, i.e., real :: 'a => real, but it is not necessarily defined for all possible types 'a. This is easily seen when using find_theorems: when searching for lemmas on real :: nat => real, you get plenty of results whereas searching for real :: real => real doesn't give you a single result.
find_theorems "real :: real => real"
find_theorems "real :: nat => real"
Consequently, you can not even prove a simple lemma like func x = x, since it is not specified that real :: real => real really is the identity function.