759 |
759 |
760 constdefs |
760 constdefs |
761 setsum :: "('a => 'b) => 'a set => 'b::comm_monoid_add" |
761 setsum :: "('a => 'b) => 'a set => 'b::comm_monoid_add" |
762 "setsum f A == if finite A then fold (op + o f) 0 A else 0" |
762 "setsum f A == if finite A then fold (op + o f) 0 A else 0" |
763 |
763 |
|
764 text{* Now: lot's of fancy syntax. First, @{term "setsum (%x. e) A"} is |
|
765 written @{text"\<Sum>x\<in>A. e"}. *} |
|
766 |
764 syntax |
767 syntax |
765 "_setsum" :: "idt => 'a set => 'b => 'b::comm_monoid_add" ("(3\<Sum>_:_. _)" [0, 51, 10] 10) |
768 "_setsum" :: "idt => 'a set => 'b => 'b::comm_monoid_add" ("(3\<Sum>_:_. _)" [0, 51, 10] 10) |
766 syntax (xsymbols) |
769 syntax (xsymbols) |
767 "_setsum" :: "idt => 'a set => 'b => 'b::comm_monoid_add" ("(3\<Sum>_\<in>_. _)" [0, 51, 10] 10) |
770 "_setsum" :: "idt => 'a set => 'b => 'b::comm_monoid_add" ("(3\<Sum>_\<in>_. _)" [0, 51, 10] 10) |
768 syntax (HTML output) |
771 syntax (HTML output) |
769 "_setsum" :: "idt => 'a set => 'b => 'b::comm_monoid_add" ("(3\<Sum>_\<in>_. _)" [0, 51, 10] 10) |
772 "_setsum" :: "idt => 'a set => 'b => 'b::comm_monoid_add" ("(3\<Sum>_\<in>_. _)" [0, 51, 10] 10) |
770 translations |
773 translations |
771 "\<Sum>i:A. b" == "setsum (%i. b) A" -- {* Beware of argument permutation! *} |
774 "\<Sum>i:A. b" == "setsum (%i. b) A" -- {* Beware of argument permutation! *} |
|
775 |
|
776 text{* Instead of @{term"\<Sum>x\<in>{x. P}. e"} we introduce the shorter |
|
777 @{text"\<Sum>x|P. e"}. *} |
|
778 |
|
779 syntax |
|
780 "_qsetsum" :: "idt \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(3SUM _ | / _./ _)" [0,0,10] 10) |
|
781 syntax (xsymbols) |
|
782 "_qsetsum" :: "idt \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(3\<Sum>_ | (_)./ _)" [0,0,10] 10) |
|
783 syntax (HTML output) |
|
784 "_qsetsum" :: "idt \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(3\<Sum>_ | (_)./ _)" [0,0,10] 10) |
|
785 |
|
786 translations "\<Sum>x|P. t" => "setsum (%x. t) {x. P}" |
|
787 |
|
788 print_translation {* |
|
789 let |
|
790 fun setsum_tr' [Abs(x,Tx,t), Const ("Collect",_) $ Abs(y,Ty,P)] = |
|
791 (if x<>y then raise Match |
|
792 else let val x' = Syntax.mark_bound x |
|
793 val t' = subst_bound(x',t) |
|
794 val P' = subst_bound(x',P) |
|
795 in Syntax.const "_qsetsum" $ Syntax.mark_bound x $ P' $ t' end) |
|
796 in |
|
797 [("setsum", setsum_tr')] |
|
798 end |
|
799 *} |
|
800 |
|
801 text{* As Jeremy Avigad notes: ultimately the analogous |
|
802 thing should be done for setprod as well \dots *} |
772 |
803 |
773 |
804 |
774 lemma setsum_empty [simp]: "setsum f {} = 0" |
805 lemma setsum_empty [simp]: "setsum f {} = 0" |
775 by (simp add: setsum_def) |
806 by (simp add: setsum_def) |
776 |
807 |