How to use word_rsplit - isabelle

There is a function called word_rsplit in ~~/src/HOL/Word/Word.thy.
definition word_rsplit :: "'a :: len0 word => 'b :: len word list" where
"word_rsplit w =
map word_of_int (bin_rsplit (len_of TYPE ('b)) (len_of TYPE ('a), uint w))"
I want to split a 32 word to four 8 word, this function seems to be perfect.
And lemma word_rcat (word_rsplit w) = w is useful for me too.
So I need to know how to use word_rsplit, how to specify 'a = 32 and 'b = 8.

To obtain a variant of word_rsplit for specific word types, you can just give explicit type constraints. E.g., your example where you want to split a 32 word into several 8 words, could be specified as follows:
word_rsplit :: 32 word => 8 word list"
Example:
value "(word_rsplit :: 32 word ⇒ 8 word list) 1024"
produces
"[0, 0, 4, 0]"
:: "8 word list"

Related

CARD of typedef of 0 to 7 nat

Update 2 (151015)
I put some source below. It shows a skeleton of what I may use.
With some help, I'm getting more sophisticated. I now know the difference between a numeral type type, and a constant of type numeral. The notation is all the same, and I'm used to using functions that operate on terms, not types. With CARD, that changes the paradigm some.
As far as numeral type notation, even with show_consts, it's not obvious that I'm looking at a type or a term. So, I draw off always using show_sorts and show_consts. A 0-ary type constructor type, like nat, never gets annotated with anything. Knowing that helps.
I said that a certain theorem wasn't being proved by magic without not importing Numeral_Type, but that's not true.
Succinct syntax is important, so getting good type inference is important. It looks like I get good type inference when using the numeral type.
From the answer, I also got my first use of using a dummy type, which, at this point, appears to be a much better way to do things.
Here's some source:
theory i151013c_numeral_has_type_enforcement
imports Complex_Main "~~/src/HOL/Library/Numeral_Type"
begin
declare [[show_sorts, show_consts]]
datatype ('a,'size) vD = vC "'a list"
definition CARD_foo :: "('a,'s::{finite,card_UNIV}) vD => ('a,'s) vD => nat"
where
"CARD_foo x y = card (UNIV :: 's set)"
notation (input) vC ("vC|_" [1000] 1000)
notation (output) vC ("vC|_" [1000] 999)
value "CARD_foo (vC|x::(nat,32) vD) vC|y = (32::nat)" (*True*)
value "CARD_foo (vC|x::(nat,65536) vD) vC|y = 65536" (*True*)
type_synonym nv3 = "(nat, 3) vD"
notation CARD_foo (infixl "*+*" 65)
value "vC|m *+* (vC|n::nv3) = 3" (*True*)
type_notation (input) vD ("< _ , _ >")
term "x::<'a,'s::{finite,card_UNIV}>"
term "vC|m *+* (vC|n::<'a,64>) = 64"
value "vC|m *+* (vC|n::<'a,64>) = 64" (*True*)
(*Next, Am I adding 2 types of type numeral? Or am I adding 2 constants of
type numeral, which produces a numeral type? The notation for numeral types
and numeral type constants is identical.*)
value "vC|[3] *+* (vC|y::<nat,2 + 3>)"
term "vC|[3] *+* (vC|y::<nat,2 + 3>)"
(*I guess 2 and 3 are types. In the output panel, 0-ary types, such as 'nat',
don't get annotated with anything, where nat constants do.*)
lemma "vC|[3] *+* (vC|y::<nat,2 + 3>) = 5"
by(simp add: CARD_foo_def)
(*Type error clash. Oh well. Just don't do that.*)
term "(vC|x::<'a,5>) *+* (vC|y::<'a,2 + 3>)"
definition vCARD :: "('a, 's::{finite,card_UNIV}) vD => nat" where
"vCARD x = CARD('s)"
declare vCARD_def [simp add]
lemma
"vCARD(x::<'a,'s::{finite,card_UNIV}>) =
vCARD(y::<'b,'s::{finite,card_UNIV}>)"
by(simp)
end
Update (151014)
Here I explain to M.Eberl why I don't use the numeral type, based upon what I know and have experienced.
Related comment about typedef and a past question
A while back, I got exposed to ~~/src/HOL/Library/Cardinality, along with Numeral_Type from this answer by M.Eberl:
Trying to generalize a bit vector that uses typedef, bool list, and nat length
That question was also related to typedef. Partly from my experiments at that time, I try to stay away from typedef, and use the magic that comes with datatype.
Even today, I started having problems with the sz8 typedef not working with value, because of abstraction problems. After looking back at the answer linked to above, it partially shows what has to be done to get typedef working with value. I have a size8 in the new source I include that shows what I did. I think there's a problem with the equal function, that it needs to be fixed similar to what's shown in the answer above.
An Example size datatype and vector datatype
Now, I make a few comments about the two example datatypes in the second source I include below.
The use case for a size type is for vector length, where the vectors are lists.
The size type enforces that for a binary operation, two vectors have the same length. I then only have to check that the two vectors actually are the right length.
The problem with the numeral type is that there's no type enforcement. My example function has the following signature, with the datatype shown:
datatype ('a,'size) vD = vC "'a list" 'size
CARD_foo :: "(nat,'s::card_UNIV) vD => (nat,'s) vD => nat"
But I can to this:
term "CARD_foo (vC [] 10) (vC [] 11)"
Other comments are in the source. I have a typedef size8 at the end, and I don't know, at this time, how to fix that.
Though there's no type enforcement with the numeral type, I guess I can depend on type size using CARD, based on this:
theorem CARD_of_type_of_terms_of_same_type_are_equal:
"CARD_foo (vC n size1term) = CARD_foo (vC m size2term)"
unfolding CARD_foo_def
by(auto simp add: CARD_foo_def)
To get that by magic, I had to not import "~~/src/HOL/Library/Numeral_Type".
Thanks for the help. It's invaluable, and thanks for how to get the proofs I asked for originally. It helps to learn things here and there about typedef.
The new example source:
theory i151013b_2nd
imports Complex_Main (*"$GEZ/e/IsE"*)
"~~/src/HOL/Library/Cardinality" "~~/src/HOL/Library/Numeral_Type"
begin
declare [[show_sorts, show_consts]]
(*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*)
(*::¦ NUMERAL TYPE DOESN'T GUARANTEE TYPE ENFORCEMENT FOR A BINARY OP ¦:::*)
(*----------------------------*)
(*The size type as a datatype.*)
datatype sz8D = sz8C bool bool bool
(*-----------------------------------*)
(*Typdef 'n <= 7 would be preferable.*)
lemma UNIV_sz8D:
"UNIV =
{sz8C False False False, sz8C False False True, sz8C False True False,
sz8C False True True, sz8C True False False, sz8C True False True,
sz8C True True False, sz8C True True True}"
by(auto, metis (full_types) sz8D.exhaust)
lemma card_UNIV_sz8D [simp]: "card (UNIV :: sz8D set) = 8"
by(unfold UNIV_sz8D, auto)
instantiation sz8D :: card_UNIV
begin
definition "finite_UNIV = Phantom(sz8D) True"
definition "card_UNIV = Phantom(sz8D) 8"
instance
apply(default)
unfolding UNIV_sz8D finite_UNIV_sz8D_def card_UNIV_sz8D_def
by(auto)
end
(*-----------------------------------------*)
(*The vector type with an example function.*)
datatype ('a,'size) vD = vC "'a list" 'size
definition CARD_foo :: "(nat,'s::card_UNIV) vD => (nat,'s) vD => nat" where
"CARD_foo x y = card (UNIV :: 's set)"
thm CARD_foo_def
(*--------------------------------------------------------*)
(*sz8D: Size enforcement. Error if I mix other size types.*)
value "CARD_foo (vC [] (s::sz8D)) (vC [1] (t::sz8D))" (*outputs 8*)
value "CARD_foo (vC [] (sz8C False False False)) (vC [1] (t::sz8D))"
(*-------------------------------------*)
(*numeral: No enforcement of size type.*)
term "CARD_foo (vC [] 10) (vC [] 11)" (*
"CARD_foo (vC [] (10::'a::{card_UNIV,numeral}))
(vC [] (11::'a::{card_UNIV,numeral}))" :: "nat" *)
(*Can't eval the type to nat, even if they're the same*)
value "CARD_foo (vC [] 10) (vC [] 10)"
(*But here, CARDs are different anyway; no enforcement, no value.*)
value "CARD_foo (vC [] 10) (vC [] 11)" (*
"of_phantom card_UNIV_class.card_UNIV" :: "nat"*)
lemma "CARD_foo (vC [] 10) (vC [] 11) = z" oops (*
show_consts:
CARD_foo (vC [] (10::'a)) (vC [] (11::'a)) = z
'a :: {card_UNIV,numeral} *)
(*Can evaluate when there's not a conflict.*)
term "CARD(10)"
value "CARD(10)" (*outputs 10*)
lemma "CARD(10) = 10" by simp (*show_consts: 'UNIV :: 10 set'*)
value "CARD(11)" (*outputs 11*)
(*No eval if CARD('a) is used in a function.*)
definition fooID :: "'a::card_UNIV => nat" where
"fooID x = CARD('a)"
term "fooID(5)"
value "fooID(5)"
(*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*)
(*::¦ HOWEVER, BY FUNCTION UNIQUENESS, I SUPPOSE THERE'S NO AMBIGUITY ¦:::*)
(*[>) I have to drop down to only 'src/HOL/Library/Cardinality' to get this.
[>) For some reason, it won't unfold the definition.*)
theorem CARD_of_type_of_terms_of_same_type_are_equal:
"CARD_foo (vC n size_1term) = CARD_foo (vC m size_2term)"
unfolding CARD_foo_def
by(auto simp add: CARD_foo_def)
(*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*)
(*::¦ CAN'T USE TYPEDEF AFTERALL IF I CAN'T FIX THIS ¦::::::::::::::::::::*)
(*NOTE ABOUT PLUG'N'PLAY:
[>) See http://stackoverflow.com/q/27415275
[>) 'value' for 'CARD_foo' needs class 'equal'
[>) '[code abstract]' didn't work, so I used '[code]'.*)
typedef size8 = "{n::nat. n ≤ 7}"
morphisms size8_to_nat Abs_size8
by(blast)
definition nat_to_size8 :: "nat => size8" where
"nat_to_size8 n == if n ≤ 7 then Abs_size8 n else Abs_size8 0"
lemma nat_to_size8_code [code]:
"size8_to_nat (nat_to_size8 n) = (if n ≤ 7 then n else 0)"
unfolding nat_to_size8_def
by(simp add: Abs_size8_inverse)
setup_lifting type_definition_size8
instantiation size8 :: equal
begin
lift_definition equal_size8 :: "size8 => size8 => bool" is "λx y. x = y" .
instance
by(default, transfer, auto simp add: equal_size8_def)
end
instantiation size8 :: card_UNIV
begin
definition "finite_UNIV = Phantom(size8) True"
definition "card_UNIV = Phantom(size8) 8"
instance sorry
end
value "CARD_foo (vC [] (Abs_size8 0)) (vC [] (Abs_size8 0))" (*
Abstraction violation: constant Abs_size8 *)
end
Original Question
I'm using typedef to define some types that are used as size types, to be used like this: CARD(sz8). I can use datatype, but it takes a lot longer for it to set itself up.
I guess I don't understand how to show two values are unique with the inverse theorems generated by typedef for sz8.
I have my type, sz8, and I instantiate it as card_UNIV. What's incomplete is my theorem card_UNIV_sz8, which is "card (UNIV::sz8 set) = 8".
theory i151013a
imports Complex_Main "~~/src/HOL/Library/Cardinality"
"$GEZ/e/IsE"
begin
declare [[show_sorts, show_consts]]
typedef sz8 = "{n::nat. n ≤ 7}"
by(blast)
theorem UNIV_sz8:
"UNIV = {s::sz8. ∃n. n ≤ 7 ∧ s = Abs_sz8 n}"
using Rep_sz8 Rep_sz8_inverse
by(fastforce)
theorem foo1:
assumes "Abs_sz8 n ∈ {s::sz8. ∃n ≤ 7. s = Abs_sz8 n}"
shows "n ∈ {n. n ≤ 7}"
proof
fix n :: nat
note assms
obtain n1 where
f1: "n1 ≤ (7::nat) ∧ Abs_sz8 n = Abs_sz8 n1"
using Rep_sz8 Rep_sz8_inverse
by(fastforce)
hence "n = n1"
oops
find_theorems name: "sz8"
instance sz8 :: finite
apply default
unfolding UNIV_sz8
by(simp)
theorem card_UNIV_sz8 [simp]:
"card (UNIV::sz8 set) = 8"
unfolding UNIV_sz8
sorry
instantiation sz8 :: card_UNIV
begin
definition "finite_UNIV = Phantom(sz8) True"
definition "card_UNIV = Phantom(sz8) 8"
instance
apply default
unfolding finite_UNIV_sz8_def card_UNIV_sz8_def
by(simp_all)
end
end
The answer to your question
First of all: I will answer your question, but then I will tell you why what you are doing is unnecessary.
You can show the distinctness of the values using the theorem sz8.Abs_sz8_inject, which shows up if you do find_theorems Abs_sz8:
(?x::nat) ∈ {n::nat. n ≤ (7::nat)} ⟹
(?y::nat) ∈ {n::nat. n ≤ (7::nat)} ⟹
(Abs_sz8 ?x = Abs_sz8 ?y) = (?x = ?y)
You can prove your theorem e.g. like this:
lemma sz8_image: "x ∈ Abs_sz8 ` {0..7}"
by (cases x rule: sz8.Abs_sz8_cases) auto
theorem card_UNIV_sz8 [simp]: "card (UNIV::sz8 set) = 8"
proof -
from sz8_image have "UNIV = Abs_sz8 ` {0..7}" by blast
also from sz8.Abs_sz8_inject have "card … = card {0..(7::nat)}"
by (intro card_image inj_onI) simp_all
finally show ?thesis by simp
qed
What you should do instead
Have a look at the theory ~~/src/HOL/Library/Numeral_Type, where ~~ stands for the Isabelle root directory.
This defines a type n for every positive integer n, which contains exactly the numbers from 0 to n - 1 and even defines lots of typeclass instances and modular arithmetic on them. For example:
value "(2 - 5 :: 10) = 7"
> "True" :: "bool"
This is probably exactly what you want and it comes fully set up; doing all of this by hand is quite tedious, and if you ever need a size 16 type, you have to do the same thing all over again.
Update: More on numeral types
In your updated question, you claim that type checking for numeral types does not work. That is not correct; the problem is merely that the 10 in your vC [] 10 has no meaning. Your intention was probably to specify that the length parameter 'size in the type of that function must be 10.
However, every numeral type contains a 10. For instance, (10 :: 5) = 0 and (10 :: 6) = 4. Therefore, the 10 and 11 in there do not cause any type restrictions at all.
What you have to do is constrain 'size at the type level:
datatype ('a,'size) vD = vC "'a list"
consts CARD_foo :: "(nat,'s::card_UNIV) vD => (nat,'s) vD => nat"
term "CARD_foo (vC [] :: (nat, 10) vD) (vC [] :: (nat, 11) vD)"
(* Type error *)
If you really want to do something on the value-level similar to what you tried to do, you can use the following trick:
datatype ('a,'size) vD = vC "'a list" "'size itself"
consts CARD_foo :: "(nat,'s::card_UNIV) vD => (nat,'s) vD => nat"
term "CARD_foo (vC [] TYPE(10)) (vC [] TYPE(11))"
'a itself is basically a singleton type that contains the value TYPE('a). I think the variant without these itself values is probably more convenient in the long run though.
As for why your CARD_of_type_of_terms_of_same_type_are_equal does not work, I cannot say without seeing the definition of the constants involved, I am quite sure that everything that works with your hand-crafted sz8 type will work with numeral types.
At the end of the day, you can always replace sz8 everywhere in your code with 8 and everything should still work.

need a definition in Isabelle to show that two partial functions never produce the same output

I'm using the mathematical toolkit in HOL-Z to discharge some Isabelle predicates. specifically I'm using the partial function definition to define some of the relations in a Z specification that I'm writing, where I convert the schema's to Specification statements so that I can generate simple HOL predicates.
definitions from HOL-Z toolkit
type_synonym ('a,'b) lts = "('a*'b) set" (infixr "<=>" 20)
prodZ ::"['a set,'b set] => ('a <=> 'b) " ("_ %x _" [81,80] 80)
"a %x b" == "a <*> b"
rel ::"['a set, 'b set] => ('a <=> 'b) set" ("_ <--> _" [54,53] 53)
rel_def : "A <--> B == Pow (A %x B)"
partial_func ::"['a set,'b set] => ('a <=> 'b) set" ("_ -|-> _" [54,53] 53)
partial_func_def : "S -|-> R ==
{f. f:(S <--> R) & (! x y1 y2. (x,y1):f & (x,y2):f --> (y1=y2))}"
rel_appl :: "['a<=>'b,'a] => 'b" ("_ %^ _" [90,91] 90)
rel_appl_def : "R %^ x == (#y. (x,y) : R)"
When I write the following within a predicate:
FORALL x. balance %^ x = Bbalance %^ x
where balance and Bbalance are both partial functions(in Z), of the form ('a <=> 'b) in Isabelle, I assume it behaves fine.
How can I define another function where I say that the two partial functions are totally disjoint for all 'x' . I mean the relational application of the same value on two partial functions 'balance' and 'Bbalance' NEVER produce the same value. something like...
FORALL x. balance %^ x \noteq Bbalance %^ x
sorry for the poor explanation. we learn through expert advice :).
Your rel_appl_def rule makes use of the epsilon function. According to the Stanford Encyclopedia of Philosophy (SEP)(*) in his Hamburg lecture in 1921 (1922), Hilbert first presented the idea of using choice functions to deal with the principle of the excluded middle in a formal system for arithmetic.
The governing axiom of the epsilon function reads as follows:
(A x) --> (A (# A))
In classical logic, because of ex falso quodlibet, if (A x) fails, (# A) can take any interpretation. This means that your rel_appl_def rule gives any value when you supply an argument x that is not in the domain dom R.
So probably what you want to use as equality would be the following boolean function (^) on two partial functions:
f ^ g = (dom f = dom g) & (!x. x : dom f --> f %^ x = g %^ x)
What I cannot understand when SEP writes, the second, of perhaps greater current interest, is the use of the epsilon-operator in the theorem-proving systems HOL and Isabelle, where the expressive power of epsilon-terms yields significant practical advantages.
I have seen a much simpler treatment of partial functions in practice, namely using the option type. So a partial function f belongs simply to a type A => B option. But when you cannot change the types in your project, it is probably wiser to seek the equality that fits your requirements, the above definition could be a candidate.
Bye
(*)
The Epsilon Calculus, Jeremy Avigad and Richard Zach
First published Fri May 3, 2002; substantive revision Wed Nov 27, 2013
http://plato.stanford.edu/entries/epsilon-calculus/

Trying to generalize a bit vector that uses typedef, bool list, and nat length

I investigated Coq a little, with its dependent types. I have only the foggiest idea about it all, but now I have in mind that I want a bit vector as a bool list, in which the length of the vector is part of the type.
(This question is the possible predecessor of another question. In the next question, if I ask it, I'll ask whether I can recover what I lose, when I use typedef as below.)
(For this question, the question is at the bottom)
Here are the requirements for the type I want:
It has to use bool list, so that I can directly or indirectly do pattern matching and recursion on the list, and
the length of the vector has to be specified in the type.
Here is what I have:
typedef bitvec_4 = "{bl::bool list. length bl = 4}"
by(auto, metis Ex_list_of_length)
It's important that the length of the list be part of the type, because I want to use the type with a definition, where all lists are known to be of the same size, like with this simple example:
definition two_bv4_to_bv4 :: "bitvec_4 => bitvec_4 => bitvec_4" where
"two_bv4_to_bv4 x y = x"
What I don't want, in a theorem, is to have to specify the length of the lists. Type classes would eventually come into play somehow, but I want, as I say, the length to be specified in the type definition.
Definition and type signatures. Where do I let n = 4!!? (a tech joke of minimal humor-value)
Now, I try to generalize with a typedef like this, in which the length is a variable:
typedef bitvec_n = "{(bl::bool list, n::nat). length bl = n}"
by(auto)
That's no good. In a definition like this next one, my type doesn't guarantee that all lists are of the same length:
definition two_bvn_to_bvn :: "bitvec_n => bitvec_n => bitvec_n" where
"two_bvn_to_bvn x y = x"
The question? (I think so)
I've experimented a little with types like bitvec_4 above. If I don't run into big roadblocks, I might try to make big use of them.
I could define types like the above for powers of 2, up to, say, 1024 bits, along with type classes that reflect their common properties.
But, is there a better way to do this? It has to be somewhat straightforward, I think, with the use of bool list.
Update (got the answer for what it was actually about)
Based on Manuel's answer, I include here a self-contained theory.
It's mostly a duplication of Manuel's source, but at the end, my functions swap_bl and swap_2bv, along with the final use of value, show the end result of what I was trying to accomplish. My comments emphasize the problems that were on my mind, and possibly, my end application shows why I haven't looked to HOL/Word as a solution.
For a typedef type, to do pattern matching indirectly, similar to that with swap_bl and 2 bitvec, I was using the Abs and Rep functions together as inverses. One problem, as Manuel pointed out, is that I can feed an Abs function a bool list of the wrong length, and it won't give an error. Another big problem is the abstraction violations due to the use of the Abs function.
Those problems, and wanting to know if I could recover the use of value for my typedef type, would have been parts of my next question, but all that's been answered here.
theory i141210ac__testing_out_manuels_answer
imports Main "~~/src/HOL/Library/Numeral_Type"
begin
(*Basic type definition.*)
typedef ('n::finite) bitvec = "{bs :: bool list. length bs = CARD('n)}"
morphisms bitvec_to_list Abs_bitvec
by (simp add: Ex_list_of_length)
setup_lifting type_definition_bitvec
lift_definition nth :: "('n::finite) bitvec => nat => bool" (infixl "$" 90)
is List.nth .
(*Can't use 'value' yet for 'nth', or I get an abstraction violation.*)
term "(Abs_bitvec [True,False] :: 2 bitvec) $ 1"
(*Truncate or fill the list: needed to set things up for 'value'.*)
definition set_length :: "nat => bool list => bool list" where
"set_length n xs = (if length xs < n
then xs # replicate (n - length xs) False
else take n xs)"
lemma length_set_length [simp]: "length (set_length n xs) = n"
unfolding set_length_def by auto
definition list_to_bitvec :: "bool list => ('n::finite) bitvec" where
"list_to_bitvec xs = Abs_bitvec (set_length CARD('n) xs)"
(*Finishing the magic needed for 'value'.*)
lemma list_to_bitvec_code [code abstract]:
"bitvec_to_list (list_to_bitvec xs :: ('n::finite) bitvec)
= set_length CARD('n) xs"
unfolding list_to_bitvec_def by(simp add: Abs_bitvec_inverse)
(*Inverses for lists of length 2: no abstraction violations.*)
value "list_to_bitvec (bitvec_to_list x) :: 2 bitvec"
value "bitvec_to_list (list_to_bitvec x :: 2 bitvec)"
(*The magic now kicks in for 'value' and 'nth'. Understanding is optional.*)
value "(list_to_bitvec [True,False] :: 2 bitvec) $ 1" (*OUTPUT: False.*)
(*For my use, the primary context of all this is pattern matching on lists.
I can't pattern match on a 'typedef' type directly with 'fun', because
it's not a 'datatype'. I do it indirectly.*)
fun swap_bl :: "bool list => bool list" where
"swap_bl [a,b] = [b,a]"
|"swap_bl _ = undefined"
definition swap_2bv :: "2 bitvec => 2 bitvec" where
"swap_2bv bv = list_to_bitvec (swap_bl (bitvec_to_list bv))"
value "swap_2bv (list_to_bitvec [a,b] :: 2 bitvec)" (*
OUTPUT: "Abs_bitvec [b, a]" :: "2 bitvec" *)
(*Whether that's all a good idea, that's about the future, but it appears the
hard work, recovering the use of 'value', along with generalizing length,
has been done by Manuel, and the authors of Numeral_Type and its imports.*)
end
Isabelle does not support dependent types, but there are ways to still do what you want to do. For instance, there is already a stack of type classes and type syntax for type-level natural numbers.
theory Scratch
imports Main "~~/src/HOL/Library/Numeral_Type"
begin
lemma "(UNIV :: 4 set) = {0,1,2,3}"
by (subst UNIV_enum) eval
As you can see, the type 4 is a type that contains the numbers from 0 to 3. Incidentally, this can also be used for computations in modular arithmetic:
lemma "((2 + 3) :: 4) = 1" by simp
lemma "((2 * 3) :: 4) = 2" by simp
You can use these numeral types to parametrise your bit vectors with a length:
typedef ('n::finite) bitvec = "{bs :: bool list. length bs = CARD('n)}"
morphisms bitvec_to_list Abs_bitvec
by (simp add: Ex_list_of_length)
setup_lifting type_definition_bitvec
You can access the n-th element of a bit vector by lifting the nth function from Boolean lists to bit vectors, which works automatically:
lift_definition nth :: "('n::finite) bitvec ⇒ nat ⇒ bool" (infixl "$" 90) is List.nth .
Converting boolean lists to bit vectors is a bit tricky, because the list you get in might not have the correct length; the expression list_to_bitvec [True] :: 2 bitvec would typecheck, but is obviously problematic. You could solve this either by returning undefined or, perhaps more appropriate in this instance, filling up the list with False or truncating it to get the right length:
definition set_length :: "nat ⇒ bool list ⇒ bool list" where
"set_length n xs = (if length xs < n then xs # replicate (n - length xs) False else take n xs)"
lemma length_set_length[simp]: "length (set_length n xs) = n"
unfolding set_length_def by auto
Now we can define a function that converts a list of Booleans to a bit vector:
definition list_to_bitvec :: "bool list ⇒ ('n::finite) bitvec" where
"list_to_bitvec xs = Abs_bitvec (set_length CARD('n) xs)"
However, we are not allowed to use Abs_bitvec in code equations; if you tried to evaluate, say, list_to_bitvec [True] :: 1 bitvec, you would get an abstraction violation. We have to give an explicit code abstract equation in terms of the morphism list_to_bitvec:
lemma list_to_bitvec_code[code abstract]:
"bitvec_to_list (list_to_bitvec xs :: ('n::finite) bitvec) = set_length CARD('n) xs"
unfolding list_to_bitvec_def by (simp add: Abs_bitvec_inverse)
And now we are basically done and can do e.g. this:
definition myvec :: "4 bitvec" where "myvec = list_to_bitvec [True, False, True]"
value myvec
(* Output: "Abs_bitvec [True, False, True, False]" :: "4 bitvec" *)
value "myvec $ 2"
(* Output: "True" :: "bool" *)
Note that you always have to annotate the result of list_to_bitvec with its length; Isabelle can not infer the length.
You may also want to have a look at the Word theory in ~~/src/HOL/Word/; it implements machine words of fixed length with all kinds of bit operations like NOT, AND, OR, etc.:
value "42 AND 23 :: 32 word"
(* Output: "2" :: "32 word" *)
value "293 :: 8 word"
(* Output: "37" :: "8 word" *)
value "test_bit (42 :: 8 word) 1"
(* Output: "True" :: "bool" *)
value "set_bit (42 :: 8 word) 2 True"
(* Output: "46" :: "8 word" *)
value "(BITS i. i < 4) :: 8 word"
(* Output: "15" :: "8 word" *)
Another related type are the vectors in src/HOL/Library/Multivariate_Analysis/Finite_Cartesian_Product.

Function cannot use type inference, but I don't understand why

So here is my goofy sandbox to play with Applicatives in PureScript
module Main where
import Debug.Trace
data Foo a
= Foo a
instance showFoo :: (Show a) => Show (Foo a) where
show (Foo a) = "I pity da (Foo " ++ (show a) ++ ")"
instance functorFoo :: Functor Foo where
(<$>) f (Foo a) = Foo (f a)
instance applyFoo :: Apply Foo where
(<*>) (Foo a) (Foo b) = Foo (a b)
m :: Number -> Number -> Number -> Number
m x y z = x * y - z
main = trace <<< show $ m <$> Foo 14
<*> Foo 2
<*> Foo 5
The above works fine, but if I remove:
m :: Number -> Number -> Number -> Number
it does not compile
Error at pure.purs line 18, column 1:
Error in declaration m
No instance found for Prelude.Num u1150
However (+) and (-) are both of type
forall a. (Prelude.Num a) => a -> a -> a
Why can't Number be inferred?
The reality is that when learning PureScript and coming from a dynamic language (JavaScript), I run into type errors frequently. Developing skills in diagnosing and understanding these errors is challenging without a grasp of when inference can occur and when it can't. Otherwise I will have to write types every single time in order to feel confident in my code (lameness).
This is because at the moment the compiler can't infer typeclass constraints, and as you noted the arithmetic operators are all defined in the Num typeclass.
The type that would be inferred for m (if the compiler could) would be something like:
m :: forall a. (Num a) => a -> a -> a -> a
On your second point typing top level declarations is considered good style anyway, as it helps to document your code: see here for a fuller explanation.

How can I convert my data type?

I define a data type for a multi list:
datatype intnest= INT of int
| LIST of intnest list;
now I'm trying to write function which can convert this type to main type.
for example:
[INT 1, INT 2, LIST[INT 6, INT 8]] => [1,2, [6,8]]
how can I do this?
thanks in advance for any help
With reference to your previous question, you can't!
As i tried to explain: It is not possible to have such a value in SML!
Just try it out in your interpreter
- val _ = [1,2, [6,8]];
stdIn:28.9-28.21 Error: operator and operand don't agree [literal]
operator domain: int * int list
operand: int * int list list
in expression:
2 :: (6 :: 8 :: nil) :: nil
If we construct the list with the basic constructs instead of the syntactic sugar, then the list [1,2,3] becomes 1 :: 2 :: 3 :: nil
Now, if we look at the types of the two "building blocks" cons and nil
- op::;
val it = fn : 'a * 'a list -> 'a list
- nil;
val it = [] : 'a list
then we see that the infix operator cons, takes an argument of type 'a on the left hand side and a list of 'a on the right hand side.
Thus we can see that if we build a list of ints, then we must give it an int on the left hand side and a list of ints on the right hand side (as the example above). It should be clear from this that we can't to anything like this:
[1, 2] :: 3 :: nil
which is equivalent with (1 :: 2 :: nil) :: 3 :: nil

Resources