theory Test_Polymorphic_Classes imports Isabelle_DOF.Isa_DOF TestKit begin doc_class title = short_title :: "string option" <= "None" doc_class Author = email :: "string" <= "''''" datatype classification = SIL0 | SIL1 | SIL2 | SIL3 | SIL4 doc_class abstract = keywordlist :: "string list" <= "[]" safety_level :: "classification" <= "SIL3" doc_class text_section = authored_by :: "Author set" <= "{}" level :: "int option" <= "None" doc_class ('a::one, 'b, 'c) test0 = text_section + testa :: "'a list" testb :: "'b list" testc :: "'c list" typ\('a, 'b, 'c) test0\ typ\('a, 'b, 'c, 'd) test0_scheme\ find_consts name:"test0" find_theorems name:"test0" doc_class 'a test1 = text_section + test1 :: "'a list" invariant author_finite_test :: "finite (authored_by \)" invariant force_level_test :: "(level \) \ None \ the (level \) > 1" find_consts name:"test1*inv" find_theorems name:"test1*inv" text*[church::Author, email="\b\"]\\ text\@{Author "church"}\ value*\@{Author \church\}\ text\\<^value_>\@{Author \church\}\\ doc_class ('a, 'b) test2 = "'a test1" + test2 :: "'b list" type_synonym ('a, 'b) test2_syn = "('a, 'b) test2" find_theorems name:"test2" declare [[invariants_checking_with_tactics]] text*[testtest::"('a, int) test2", level = "Some 2", authored_by = "{@{Author \church\}}", test2 = "[1]"]\\ value*\test2 @{test2 \testtest\}\ text*[testtest2''::"(nat, int) test2", test1 = "[2::nat, 3]", test2 = "[4::int, 5]", level = "Some (2::int)"]\\ value*\test1 @{test2 \testtest2''\}\ declare [[invariants_checking_with_tactics = false]] ML\ val t = Syntax.parse_term \<^context> "@{test2 \testtest\}" \ ML\ val t = \<^term>\test2.make 8142730 Test_Parametric_Classes_2_test2_authored_by_Attribute_Not_Initialized Test_Parametric_Classes_2_test2_level_Attribute_Not_Initialized Test_Parametric_Classes_2_test2_test1_Attribute_Not_Initialized Test_Parametric_Classes_2_test2_test2_Attribute_Not_Initialized \authored_by := bot, level := None\ \ \ text\test2 = "[1::'a::one]" should be test2 = "[1::int]" because the type of testtest4 is ('a::one, int) test2:\ text-assert-error[testtest4::"('a::one, int) test2", level = "Some 2", authored_by = "{@{Author \church\}}", test2 = "[1::'a::one]"]\\ \Type unification failed\ text\Indeed this definition fails:\ definition-assert-error testtest2::"('a::one, int) test2" where "testtest2 \ test2.make 11953346 {@{Author \church\}} (Some 2) [] [] \authored_by := bot , level := None, level := Some 2 , authored_by := insert \Author.tag_attribute = 11953164, email = []\ bot , test2.test2 := [1::('a::one)]\ " \Type unification failed\ text\For now, no more support of type synonyms as parent:\ doc_class ('a, 'b, 'c) A = a :: "'a list" b :: "'b list" c :: "'c list" type_synonym ('a, 'b, 'c) A_syn = "('a, 'b, 'c) A" doc_class-assert-error ('a, 'b, 'c, 'd) B = "('b, 'c, 'd) A_syn" + d ::"'a::one list" <= "[1]" \Undefined onto class: "A_syn"\ declare[[invariants_checking_with_tactics]] definition* testauthor0 where "testauthor0 \ \Author.tag_attribute = 5, email = \test_author_email\\" definition* testauthor :: "Author" where "testauthor \ \Author.tag_attribute = 5, email = \test_author_email\\" definition* testauthor2 :: "Author" where "testauthor2 \ \Author.tag_attribute = 5, email = \test_author_email\\ \email := \test_author_email_2\ \" definition* testauthor3 :: "Author" where "testauthor3 \ testauthor \email := \test_author_email_2\ \" ML\ val ctxt = \<^context> val input0 = Syntax.read_input "@{Author \church\}" val source = Syntax.read_input "\<^term_>\@{Author \church\}\" val input = source val tt = Document_Output.output_document ctxt {markdown = false} input \ doc_class ('a, 'b) elaborate1 = a :: "'a list" b :: "'b list" doc_class ('a, 'b) elaborate2 = c :: "('a, 'b) elaborate1 list" doc_class ('a, 'b) elaborate3 = d :: "('a, 'b) elaborate2 list" text*[test_elaborate1::"('a::one, 'b) elaborate1", a = "[1]"]\\ term*\@{elaborate1 \test_elaborate1\}\ value* [nbe]\@{elaborate1 \test_elaborate1\}\ text*[test_elaborate2::"('a::one, 'b) elaborate2", c = "[@{elaborate1 \test_elaborate1\}]"]\\ text*[test_elaborate3::"('a::one, 'b) elaborate3", d = "[@{elaborate2 \test_elaborate2\}]"]\\ term*\(concat o concat) ((map o map) a (map c (elaborate3.d @{elaborate3 \test_elaborate3\})))\ value*\(concat o concat) ((map o map) a (map c (elaborate3.d @{elaborate3 \test_elaborate3\})))\ text\ The term antiquotation is considered a ground term. Then its type here is \<^typ>\'a::one list\ with \'a\ a fixed-type variable. So the following definition only works because the parameter of the class is also \'a\.\ declare[[ML_print_depth = 10000]] doc_class 'a elaborate4 = d :: "'a::one list" <= "(concat o concat) ((map o map) a (map c (elaborate3.d @{elaborate3 \test_elaborate3\})))" declare[[ML_print_depth = 20]] declare[[ML_print_depth = 10000]] text*[test_elaborate4::"'a::one elaborate4"]\\ declare[[ML_print_depth = 20]] text\Bug: As the term antiquotation is considered as a ground term, its type \<^typ>\'a::one list\ conflicts with the type of the attribute \<^typ>\int list\. To support the instantiation of the term antiquotation as an \<^typ>\int list\, the term antiquotation should have the same behavior as a constant definition, which is not the case for now.\ declare[[ML_print_depth = 10000]] doc_class-assert-error elaborate4' = d :: "int list" <= "(concat o concat) ((map o map) a (map c (elaborate3.d @{elaborate3 \test_elaborate3\})))" \Type unification failed\ declare[[ML_print_depth = 20]] text\The behavior we want to support: \ definition one_list :: "'a::one list" where "one_list \ [1]" text\the constant \<^const>\one_list\ can be instantiate as an \<^typ>\int list\:\ doc_class elaborate4'' = d :: "int list" <= "one_list" declare[[ML_print_depth = 10000]] text*[test_elaborate4''::"elaborate4''"]\\ declare[[ML_print_depth = 20]] term*\concat (map a (elaborate2.c @{elaborate2 \test_elaborate2\}))\ value*\concat (map a (elaborate2.c @{elaborate2 \test_elaborate2\}))\ text\ The term antiquotation is considered a ground term. Then its type here is \<^typ>\'a::one list\ with \'a\ a fixed-type variable. So the following definition only works because the parameter of the class is also \'a\.\ declare[[ML_print_depth = 10000]] doc_class 'a elaborate5 = d :: "'a::one list" <= "concat (map a (elaborate2.c @{elaborate2 \test_elaborate2\}))" declare[[ML_print_depth = 20]] text\Bug: But when defining an instance, as we use a \'b\ variable to specify the type of the instance (\<^typ>\'b::one elaborate5\, then the unification fails\ declare[[ML_print_depth = 10000]] text-assert-error[test_elaborate5::"'b::one elaborate5"]\\ \Inconsistent sort constraints for type variable "'b"\ declare[[ML_print_depth = 20]] text\Bug: The term antiquotation is considered a ground term. Then its type here is \<^typ>\'a::one list\ with \'a\ a fixed-type variable. So it is not compatible with the type of the attribute \<^typ>\'a::numeral list\\ doc_class-assert-error 'a elaborate5' = d :: "'a::numeral list" <= "concat (map a (elaborate2.c @{elaborate2 \test_elaborate2\}))" \Sort constraint\ text\The behavior we want to support: \ text\the constant \<^const>\one_list\ can be instantiate as an \<^typ>\'a::numeral list\:\ doc_class 'a elaborate5'' = d :: "'a::numeral list" <= "one_list" text*[test_elaborate1a::"('a::one, int) elaborate1", a = "[1]", b = "[2]"]\\ term*\@{elaborate1 \test_elaborate1a\}\ value* [nbe]\@{elaborate1 \test_elaborate1a\}\ text*[test_elaborate2a::"('a::one, int) elaborate2", c = "[@{elaborate1 \test_elaborate1a\}]"]\\ text*[test_elaborate3a::"('a::one, int) elaborate3", d = "[@{elaborate2 \test_elaborate2a\}]"]\\ text\ The term antiquotation is considered a ground term. Then its type here is \<^typ>\'a::one list\ with \'a\ a fixed-type variable. So the following definition only works because the parameter of the class is also \'a\.\ definition* test_elaborate3_embedding ::"'a::one list" where "test_elaborate3_embedding \ (concat o concat) ((map o map) elaborate1.a (map elaborate2.c (elaborate3.d @{elaborate3 \test_elaborate3a\})))" text\Bug: The term antiquotation is considered a ground term. Then its type here is \<^typ>\'a::one list\ with \'a\ a fixed-type variable. So it is not compatible with the specified type of the definition \<^typ>\int list\:\ definition-assert-error test_elaborate3_embedding'::"int list" where "test_elaborate3_embedding' \ (concat o concat) ((map o map) elaborate1.a (map elaborate2.c (elaborate3.d @{elaborate3 \test_elaborate3a\})))" \Type unification failed\ term*\@{elaborate1 \test_elaborate1a\}\ value* [nbe]\@{elaborate1 \test_elaborate1a\}\ record ('a, 'b) elaborate1' = a :: "'a list" b :: "'b list" record ('a, 'b) elaborate2' = c :: "('a, 'b) elaborate1' list" record ('a, 'b) elaborate3' = d :: "('a, 'b) elaborate2' list" doc_class 'a one = a::"'a list" text*[test_one::"'a::one one", a = "[1]"]\\ value* [nbe] \@{one \test_one\}\ term*\a @{one \test_one\}\ text\Bug: The term antiquotation is considered a ground term. Then its type here is \<^typ>\'a::one list\ with \'a\ a fixed-type variable. So it is not compatible with the specified type of the definition \<^typ>\('b::one, 'a::numeral) elaborate1'\ because the term antiquotation can not be instantiate as a \<^typ>\'b::one list\ and the \'a\ is checked against the \'a::numeral\ instance type parameter:\ definition-assert-error test_elaborate1'::"('b::one, 'a::numeral) elaborate1'" where "test_elaborate1' \ \ elaborate1'.a = a @{one \test_one\}, b = [2] \" \Sort constraint\ text\This is the same behavior as the following:\ definition-assert-error test_elaborate10::"('b::one, 'a::numeral) elaborate1'" where "test_elaborate10 \ \ elaborate1'.a = [1::'a::one], b = [2] \" \Sort constraint\ definition-assert-error test_elaborate11::"('b::one, 'c::numeral) elaborate1'" where "test_elaborate11 \ \ elaborate1'.a = [1::'a::one], b = [2] \" \Type unification failed\ text\So this works:\ definition* test_elaborate1''::"('a::one, 'b::numeral) elaborate1'" where "test_elaborate1'' \ \ elaborate1'.a = a @{one \test_one\}, b = [2] \" term \elaborate1'.a test_elaborate1''\ value [nbe] \elaborate1'.a test_elaborate1''\ text\But if we embed the term antiquotation in a definition, the type unification works:\ definition* onedef where "onedef \ @{one \test_one\}" definition test_elaborate1'''::"('b::one, 'a::numeral) elaborate1'" where "test_elaborate1''' \ \ elaborate1'.a = a onedef, b = [2] \" value [nbe] \elaborate1'.a test_elaborate1'''\ definition test_elaborate2'::"(int, 'b::numeral) elaborate2'" where "test_elaborate2' \ \ c = [test_elaborate1''] \" definition test_elaborate3'::"(int, 'b::numeral) elaborate3'" where "test_elaborate3' \ \ d = [test_elaborate2'] \" doc_class 'a test3' = test3 :: "int" test3' :: "'a list" text*[testtest30::"'a::one test3'", test3'="[1]"]\\ text-assert-error[testtest30::"'a test3'", test3'="[1]"]\\ \Type unification failed: Variable\ find_consts name:"test3'.test3" definition testone :: "'a::one test3'" where "testone \ \tag_attribute = 5, test3 = 3, test3' = [1] \" definition* testtwo :: "'a::one test3'" where "testtwo \ \tag_attribute = 5, test3 = 1, test3' = [1] \\ test3 := 1\" text*[testtest3'::"'a test3'", test3 = "1"]\\ declare [[show_sorts = false]] definition* testtest30 :: "'a test3'" where "testtest30 \ \tag_attribute = 12, test3 = 2, test3' = [] \" update_instance*[testtest3'::"'a test3'", test3 := "2"] ML\ val t = @{value_ [nbe] \test3 @{test3' \testtest3'\}\} val tt = HOLogic.dest_number t \ text\@{value_ [] [nbe] \test3 @{test3' \testtest3'\}\}\ update_instance*[testtest3'::"'a test3'", test3 += "2"] ML\ val t = @{value_ [nbe] \test3 @{test3' \testtest3'\}\} val tt = HOLogic.dest_number t \ value\test3 \ tag_attribute = 1, test3 = 2, test3' = [2::int, 3] \\ value\test3 \ tag_attribute = 1, test3 = 2, test3' = [2::int, 3] \\ find_consts name:"test3'.test3" ML\ val test_value = @{value_ \@{test3' \testtest3'\}\} \ declare [[show_sorts = false]] update_instance*[testtest3'::"'a test3'", test3 += "3"] declare [[show_sorts = false]] value*\test3 @{test3' \testtest3'\}\ value\test3 \ tag_attribute = 12, test3 = 5, test3' = AAAAAA\\ find_consts name:"test3'.test3" text*[testtest3''::"int test3'", test3 = "1"]\\ update_instance*[testtest3''::"int test3'", test3' += "[3]"] value*\test3' @{test3' \testtest3''\}\ update_instance*[testtest3''::"int test3'", test3' := "[3]"] value*\test3' @{test3' \testtest3''\}\ update_instance*[testtest3''::"int test3'", test3' += "[2,5]"] value*\test3' @{test3' \testtest3''\}\ definition testeq where "testeq \ \x. x" find_consts name:"test3'.ma" text-assert-error[testtest3''::"int test3'", test3 = "1", test3' = "[3::'a::numeral]"]\\ \Type unification failed\ text-assert-error[testtest3''::"int test3'", test3 = "1", test3' = "[3]"]\\ \Duplicate instance declaration\ declare[[ML_print_depth = 10000]] definition-assert-error testest3''' :: "int test3'" where "testest3''' \ \ tag_attribute = 12, test3 = 1, test3' = [2]\\ test3' := [3::'a::numeral]\" \Type unification failed\ declare[[ML_print_depth = 20]] value* \test3 @{test3' \testtest3''\}\ value* \\ tag_attribute = 12, test3 = 1, test3' = [2]\\ test3' := [3::int]\\ value* \test3 (\ tag_attribute = 12, test3 = 1, test3' = [2]\\ test3' := [3::int]\)\ term*\@{test3' \testtest3''\}\ ML\val t = \<^term_>\test3 @{test3' \testtest3''\}\\ value\test3 \ tag_attribute = 12, test3 = 2, test3' = [2::int ,3]\\ find_consts name:"test3'.test3" find_consts name:"Isabelle_DOF_doc_class_test3'" update_instance*[testtest3''::"int test3'", test3 := "2"] ML\ val t = @{value_ [nbe] \test3 @{test3' \testtest3''\}\} val tt = HOLogic.dest_number t |> snd \ doc_class 'a testa = a:: "'a set" b:: "int set" text*[testtesta::"'a testa", b = "{2}"]\\ update_instance*[testtesta::"'a testa", b += "{3}"] ML\ val t = @{value_ [nbe] \b @{testa \testtesta\}\} val tt = HOLogic.dest_set t |> map (HOLogic.dest_number #> snd) \ update_instance-assert-error[testtesta::"'a::numeral testa", a := "{2::'a::numeral}"] \incompatible classes:'a Test_Polymorphic_Classes.testa:'a::numeral Test_Polymorphic_Classes.testa\ text*[testtesta'::"'a::numeral testa", a = "{2}"]\\ update_instance*[testtesta'::"'a::numeral testa", a += "{3}"] ML\ val t = @{value_ [nbe] \a @{testa \testtesta'\}\} \ update_instance-assert-error[testtesta'::"'a::numeral testa", a += "{3::int}"] \Type unification failed\ definition-assert-error testtesta'' :: "'a::numeral testa" where "testtesta'' \ \tag_attribute = 5, a = {1}, b = {1} \\ a := {1::int}\" \Type unification failed\ update_instance*[testtesta'::"'a::numeral testa", b := "{3::int}"] ML\ val t = @{value_ [nbe] \b @{testa \testtesta'\}\} \ value* [nbe] \b @{testa \testtesta'\}\ definition testtesta'' :: "'a::numeral testa" where "testtesta'' \ \tag_attribute = 5, a = {1}, b = {1} \\ b := {2::int}\" value [nbe]\b testtesta''\ doc_class 'a test3 = test3 :: "'a list" type_synonym 'a test3_syn = "'a test3" text*[testtest3::"int test3", test3 = "[1]"]\\ update_instance*[testtest3::"int test3", test3 := "[2]"] ML\ val t = \<^term_>\test3 @{test3 \testtest3\}\ val tt = \<^value_>\test3 @{test3 \testtest3\}\ |> HOLogic.dest_list |> map HOLogic.dest_number \ update_instance*[testtest3::"int test3", test3 += "[3]"] value*\test3 @{test3 \testtest3\}\ doc_class ('a, 'b) test4 = "'a test3" + test4 :: "'b list" definition-assert-error testtest0'::"('a::one, int) test4" where "testtest0' \ test4.make 11953346 [] [1::('a::one)]" \Type unification failed\ definition-assert-error testtest0''::"('a, int) test4" where "testtest0'' \ test4.make 11953346 [1] Test_Parametric_Classes_2_test4_test4_Attribute_Not_Initialized" \Type unification failed\ text\Must fail because the equivalent definition \testtest0'\ below fails due to the constraint in the where [1::('a::one)] is not an \<^typ>\int list\ but an \<^typ>\'a::one list\ list \ text-assert-error[testtest0::"('a::one, int) test4", test4 = "[1::'a::one]"]\\ \Type unification failed\ update_instance-assert-error[testtest0::"('a::one, int) test4"] \Undefined instance: "testtest0"\ value-assert-error\@{test4 \testtest0\}\\Undefined instance: "testtest0"\ definition testtest0''::"('a, int) test4" where "testtest0'' \ \ tag_attribute = 11953346, test3 = [], test4 = [1]\\test4 := [2]\" definition testtest0'''::"('a, int) test4" where "testtest0''' \ \ tag_attribute = 11953346, test3 = [], test4 = [1]\\test4 := [2]\" value [nbe] \test3 testtest0''\ type_synonym notion = string doc_class Introduction = text_section + authored_by :: "Author set" <= "UNIV" uses :: "notion set" invariant author_finite :: "finite (authored_by \)" and force_level :: "(level \) \ None \ the (level \) > 1" doc_class claim = Introduction + based_on :: "notion list" doc_class technical = text_section + formal_results :: "thm list" doc_class "definition" = technical + is_formal :: "bool" property :: "term list" <= "[]" datatype kind = expert_opinion | argument | "proof" doc_class result = technical + evidence :: kind property :: "thm list" <= "[]" invariant has_property :: "evidence \ = proof \ property \ \ []" doc_class example = technical + referring_to :: "(notion + definition) set" <= "{}" doc_class conclusion = text_section + establish :: "(claim \ result) set" invariant establish_defined :: "\ x. x \ Domain (establish \) \ (\ y \ Range (establish \). (x, y) \ establish \)" text\Next we define some instances (docitems): \ declare[[invariants_checking_with_tactics = true]] text*[church1::Author, email="\church@lambda.org\"]\\ text*[resultProof::result, evidence = "proof", property="[@{thm \HOL.refl\}]"]\\ text*[resultArgument::result, evidence = "argument"]\\ text\The invariants \<^theory_text>\author_finite\ and \<^theory_text>\establish_defined\ can not be checked directly and need a little help. We can set the \invariants_checking_with_tactics\ theory attribute to help the checking. It will enable a basic tactic, using unfold and auto:\ declare[[invariants_checking_with_tactics = true]] text*[curry::Author, email="\curry@lambda.org\"]\\ text*[introduction2::Introduction, authored_by = "{@{Author \church\}}", level = "Some 2"]\\ (* When not commented, should violated the invariant: update_instance*[introduction2::Introduction , authored_by := "{@{Author \church\}}" , level := "Some 1"] *) text*[introduction_test_parsed_elaborate::Introduction, authored_by = "authored_by @{Introduction \introduction2\}", level = "Some 2"]\\ term*\authored_by @{Introduction \introduction_test_parsed_elaborate\}\ value*\authored_by @{Introduction \introduction_test_parsed_elaborate\}\ text*[introduction3::Introduction, authored_by = "{@{Author \church\}}", level = "Some 2"]\\ text*[introduction4::Introduction, authored_by = "{@{Author \curry\}}", level = "Some 4"]\\ text*[resultProof2::result, evidence = "proof", property="[@{thm \HOL.sym\}]"]\\ text\Then we can evaluate expressions with instances:\ term*\authored_by @{Introduction \introduction2\} = authored_by @{Introduction \introduction3\}\ value*\authored_by @{Introduction \introduction2\} = authored_by @{Introduction \introduction3\}\ value*\authored_by @{Introduction \introduction2\} = authored_by @{Introduction \introduction4\}\ value*\@{Introduction \introduction2\}\ value*\{@{Author \curry\}} = {@{Author \church\}}\ term*\property @{result \resultProof\} = property @{result \resultProof2\}\ value*\property @{result \resultProof\} = property @{result \resultProof2\}\ value*\evidence @{result \resultProof\} = evidence @{result \resultProof2\}\ declare[[invariants_checking_with_tactics = false]] declare[[invariants_strict_checking = false]] doc_class test_A = level :: "int option" x :: int doc_class test_B = level :: "int option" x :: "string" (* attributes live in their own name-space *) y :: "string list" <= "[]" (* and can have arbitrary type constructors *) (* LaTeX may have problems with this, though *) text\We may even use type-synonyms for class synonyms ...\ type_synonym test_XX = test_B doc_class test_C0 = test_B + z :: "test_A option" <= None (* A LINK, i.e. an attribute that has a type referring to a document class. Mathematical relations over document items can be modeled. *) g :: "thm" (* a reference to the proxy-type 'thm' allowing to denote references to theorems inside attributes *) doc_class test_C = test_B + z :: "test_A option" <= None (* A LINK, i.e. an attribute that has a type referring to a document class. Mathematical relations over document items can be modeled. *) g :: "thm" (* a reference to the proxy-type 'thm' allowing to denote references to theorems inside attributes *) datatype enum = X1 | X2 | X3 (* we add an enumeration type ... *) doc_class test_D = test_B + x :: "string" <= "\def \\" (* overriding default *) a1 :: enum <= "X2" (* class - definitions may be mixed with arbitrary HOL-commands, thus also local definitions of enumerations *) a2 :: int <= 0 doc_class test_E = test_D + x :: "string" <= "''qed''" (* overriding default *) doc_class test_G = test_C + g :: "thm" <= "@{thm \HOL.refl\}" (* warning overriding attribute expected*) doc_class 'a test_F = properties :: "term list" r :: "thm list" u :: "file" s :: "typ list" b :: "(test_A \ 'a test_C_scheme) set" <= "{}" (* This is a relation link, roughly corresponding to an association class. It can be used to track claims to result - relations, for example.*) b' :: "(test_A \ 'a test_C_scheme) list" <= "[]" invariant br :: "r \ \ [] \ card(b \) \ 3" and br':: "r \ \ [] \ length(b' \) \ 3" and cr :: "properties \ \ []" lemma*[l::test_E] local_sample_lemma : "@{thm \refl\} = @{thm ''refl''}" by simp \ \un-evaluated references are similar to uninterpreted constants. Not much is known about them, but that doesn't mean that we can't prove some basics over them...\ text*[xcv1::test_A, x=5]\Lorem ipsum ...\ text*[xcv2::test_C, g="@{thm ''HOL.refl''}"]\Lorem ipsum ...\ text*[xcv3::test_A, x=7]\Lorem ipsum ...\ text\Bug: For now, the implementation is no more compatible with the docitem term-antiquotation:\ text-assert-error[xcv10::"unit test_F", r="[@{thm ''HOL.refl''}, @{thm \local_sample_lemma\}]", (* long names required *) b="{(@{docitem ''xcv1''},@{docitem \xcv2\})}", (* notations \...\ vs. ''...'' *) s="[@{typ \int list\}]", properties = "[@{term \H \ H\}]" (* notation \...\ required for UTF8*) ]\Lorem ipsum ...\\Type unification failed\ text*[xcv11::"unit test_F", r="[@{thm ''HOL.refl''}, @{thm \local_sample_lemma\}]", (* long names required *) b="{(@{test_A ''xcv1''},@{test_C \xcv2\})}", (* notations \...\ vs. ''...'' *) s="[@{typ \int list\}]", properties = "[@{term \H \ H\}]" (* notation \...\ required for UTF8*) ]\Lorem ipsum ...\ value*\b @{test_F \xcv11\}\ typ\unit test_F\ text*[xcv4::"unit test_F", r="[@{thm ''HOL.refl''}, @{thm \local_sample_lemma\}]", (* long names required *) b="{(@{test_A ''xcv1''},@{test_C \xcv2\})}", (* notations \...\ vs. ''...'' *) s="[@{typ \int list\}]", properties = "[@{term \H \ H\}]" (* notation \...\ required for UTF8*) ]\Lorem ipsum ...\ value*\b @{test_F \xcv4\}\ text*[xcv5::test_G, g="@{thm \HOL.sym\}"]\Lorem ipsum ...\ update_instance*[xcv4::"unit test_F", b+="{(@{test_A ''xcv3''},@{test_C ''xcv2''})}"] update_instance-assert-error[xcv4::"unit test_F", b+="{(@{test_A ''xcv3''},@{test_G ''xcv5''})}"] \Type unification failed: Clash of types\ typ\unit test_G_ext\ typ\\test_G.tag_attribute :: int\\ text*[xcv6::"\test_G.tag_attribute :: int\ test_F", b="{(@{test_A ''xcv3''},@{test_G ''xcv5''})}"]\\ end