Amalgamation of Render Results

namespace http://mathhub.info/ALMANAC/Context-Graph 

/T Basic example of a Dung abstract argumentation framework interpreting theories as arguments and views as attacks ❚

theory a = 

theory b = 

theory c = 

view a_attacks_b : ?a  ?b =



view b_attacks_a : ?b  ?a =



// view c_attacks_a : ?c → ?a =



// Doing Semantics: For semantics, one would have to teach MMT to compute the different semantics 
based on the views between theories. Alternativey, this could be done in the graph viewer.❚

// A larger example: ❚

theory A = 

theory B = 

theory C = 

theory D = 

theory E = 

theory F = 

theory G = 

view A_attacks_B : ?A  ?B =



view B_attacks_A : ?B  ?A =



view G_attacks_F : ?G  ?F =



view E_attacks_F : ?E  ?F =




view F_attacks_D : ?F  ?D =



view D_attacks_C : ?D  ?C =



view C_attacks_A : ?C  ?A =



view C_attacks_B : ?C  ?B =


	
/T A little bit more. First a metatheory: ❚

theory TrueFalse : ur:?LF =
prop: type 
true: prop #T 
false: prop #F 
bot: prop  #  
impl: prop ⟶ prop ⟶ prop  # 1 implies 2 
and: prop ⟶ prop ⟶ prop  # 1 and 2 
ded: prop ⟶ type  #  1 
axiom: ⊦ (T and F implies ⊥) 




theory TND : ur:?LF =
	prop: type 
	neg: prop ⟶ prop  # ¬ 1 
	impl: prop ⟶ prop ⟶ prop  # 1 implies 2 
	ded: prop ⟶ type  # ded 1 
	bot: prop  #  
	LEM1: ded {A:prop}(A implies (neg (neg A))) 
	LEM2: ded {A:prop}(neg (neg A) implies A) 



/T Now the contentious propositions:❚

theory props =
	include ?TND 
	fact1: prop 
	fact2: prop 


theory one =
	include ?TrueFalse 
	True: ⊦ T 


theory two =
	include ?TrueFalse 
	False: ⊦ F 


	
view one_attacks_two : ?one  ?two =
	include ?TrueFalse = ?TrueFalse 
	/T True = False

	
	/T The following line characterises the attack: one and two disagree allow to prove contradicting statements. Hence one attacks two on fact1 (or vice versa: these semantics for attack don't tell us enough yet to determine the correct direction of the arrow). Allowing a view to have this could e.g. involve a replacement of "=" by some contradiction operator. Note also the different between finding a view that yields a contradiction and proving that no non-contradictory view /theory-morphism is possible between the two theories.❙
	/T supports_fact1 = attacks_fact1 ❙


/T Another semantics for attack based on includes, views and conflict theories❚

theory common_ground = 
		include ?TND 
	X : prop 
	Y : prop 




theory conflict =
	include ?TND 
	C: prop 
	A: ded C 
	B: ded (C implies ⊥) 




theory three =
	include ?TND 
	X : prop 
	Y: prop 
	ass1: ded X 
	ass2: ded (X implies ¬Y) 


theory four =
	include ?TND 
	Y : prop 
	ass3: ded Y 


theory oneandthree =
	include ?three 
	include ?four 


view three_attacks_four : ?conflict  ?oneandthree =
	include ?TND = ?TND 
	C = X 
	/T A = ass1 ❙
	/T B = ded X implies ⊥ ❙
	A = ass1 

namespace http://mathhub.info/ALMANAC/JLogic/Context_Graph
import found http://mathhub.info/MitM/Foundation 

theory ABA : found:?NaturalDeduction =

assumption: bool ⟶ type  # |~ 1 prec -500
aid: {X} |~ X ⟶ ⊦ X  # aid 2 


theory Contrary : ?ABA =
contrary = not# con 1 


theory Convenience : ?ABA =
include ?Contrary 
/T some derivable rules for convenience:❙
or_elim: {A,B,C} ⊦ (A ∨ B) ⟶ (⊦ A ⟶ ⊦ C) ⟶ (⊦ B ⟶ ⊦ C) ⟶ ⊦ C  # orel 4 5 6
double_negation_introduction: {A} ⊦ A ⟶ ⊦ (¬ ¬ A)  # NI 2 
quantifier_exchange : {A:𝒰 100, B: A ⟶ prop} (⊦ ¬ ∃ [x:A] B x) ⟶ (⊦ ∀ [x:A] ¬ B x) # exch 3


fixmeta ?Convenience 

theory Arg1 =
include ?Knowledge_Base 
a1 : |~ ¬ use Tweety_example 


theory Arg2 =
include ?Knowledge_Base 
a2 : |~ ¬ ∃[x] x better Tweety_example 


theory Kernel =
w: prop 


theory Assumption =
include ?Kernel 
con1: |~ w 


theory Defeater =
include ?Kernel 
con2: ⊦ con w 


view δ : ?Kernel  ?Knowledge_Base =
w = ¬ use Tweety_example 


view φ : ?Assumption  ?Arg1 =
include 
con1 = a1 


view ψ : ?Defeater  ?Arg2 =
include 
con2 = NI (MP ax1 (aid a2)) 

namespace http://mathhub.info/ALMANAC/JLogic/Context_Graph
import found http://mathhub.info/MitM/Foundation 

fixmeta ?Convenience 

theory Ordinary_Premise =
include ?Knowledge_Base 
op: ⊦ ¬ too_complicated Meta_Tweety_example 



theory Too_Complicated_Cond =
include ?Lexicon 
comp:  example 
comp_ax: ⊦ met comp  



theory Too_Complicated_Rule =
include ?Too_Complicated_Cond 
too_complicated_proposition = too_complicated comp
too_complicated_rule: |~ met comp ⇒ too_complicated_proposition
too_complicated_arg : ⊦ too_complicated_proposition = MP (aid too_complicated_rule) comp_ax


view its_complicated : ?Too_Complicated_Cond  ?Knowledge_Base =
include ?Lexicon
comp = Meta_Tweety_example 
comp_ax = ax2


theory Too_Complicated_Pushout =
include ?Knowledge_Base 
too_complicated_app: |~ met Meta_Tweety_example ⇒ too_complicated Meta_Tweety_example
too_complicated_met : ⊦ too_complicated Meta_Tweety_example = MP (aid too_complicated_app) ax2


view met_is_complicated : ?Too_Complicated_Rule  ?Too_Complicated_Pushout =
include ?its_complicated
too_complicated_rule = too_complicated_app 
too_complicated_arg = too_complicated_met 


view Prop_complicated : ?Proposition  ?Knowledge_Base =
proposition = too_complicated Meta_Tweety_example 


view Pro_complicated : ?Pro  ?Too_Complicated_Pushout =
include ?Prop_complicated 
pro = too_complicated_met 


view Con_complicated : ?Con  ?Ordinary_Premise =
include ?Prop_complicated 
con = op 


theory Meta_is_Better_Cond =
include ?Lexicon 
ex1 : example 
ex2 : example
cond_normal : ⊦ standard ex2 
cond_met : ⊦ met ex1



theory Meta_is_Better_Rule =
include ?Meta_is_Better_Cond 
better_proposition = ex1 better ex2
better_rule : |~ met ex1 ∧ standard ex2 ⇒ better_proposition
better_arg : ⊦ better_proposition  = MP (aid better_rule) and_introduction cond_met cond_normal 



view its_better : ?Meta_is_Better_Cond  ?Ordinary_Premise =
include ?Lexicon
ex1 = Meta_Tweety_example 
ex2 = Tweety_example 
cond_met = ax2
cond_normal = ax3 


theory Meta_Pushout =
include ?Ordinary_Premise 
met_Tweety_better_proposition = Meta_Tweety_example better Tweety_example
met_Tweety_better_rule : |~ met Meta_Tweety_example ∧ standard Tweety_example ⇒ met_Tweety_better_proposition
better_arg : ⊦ met_Tweety_better_proposition  = MP (aid met_Tweety_better_rule) and_introduction ax2 ax3 


theory Dont_Use_Tweety_Example =
include ?Meta_Pushout 
no_Tweety: ⊦ ¬ use Tweety_example


view conservatively_Dont_Use_Tweety : ?Dont_Use_Tweety_Example  ?Meta_Pushout  =
include ?Meta_Pushout 
no_Tweety =  MP ax4 (existsI better_arg)


theory Default_Cond =
Prop : bool 


theory Default_Rule =
include ?Default_Cond 
default_proposition = Prop 
default : |~ ¬ default_proposition 


view Default_App_Knowledge_Base : ?Default_Cond  ?Knowledge_Base =
Prop = ∃[x] x better Tweety_example 



theory Def_Pushout =
include ?Knowledge_Base 
Def_better: |~ ¬ ∃[x] x better Tweety_example


view Pushout_Along_Default_App : ?Default_Rule  ?Def_Pushout =
include ?Default_App_Knowledge_Base 
default = Def_better 


theory Use_Tweety =
include ?Def_Pushout 
Tweety : ⊦ use Tweety_example


view conservatively_Use_Tweety : ?Use_Tweety  ?Def_Pushout =
include ?Def_Pushout 
Tweety =  MP ax1 (aid Def_better)


view undercut1 : ?Kernel  ?Knowledge_Base =
w= met Meta_Tweety_example ∧ standard Tweety_example ⇒ Meta_Tweety_example better Tweety_example 


view undercut2 : ?Assumption  ?Meta_Pushout =
include ?undercut1 
con1 = met_Tweety_better_rule


view undercut3 : ?Defeater  ?Def_Pushout =
include ?undercut1 
con2 = not_introduction [x](fals_introduction (MP x (and_introduction ax2 ax3)) forallE (exch aid Def_better) Meta_Tweety_example) 

namespace http://mathhub.info/ALMANAC/Context-Graph 
import found http://mathhub.info/MitM/Foundation 

/T How about a first-order-metatheory?❚

theory background_knowledge =
	include found:?Logic 
	include found:?InformalProofs 
	human: type 
	black: human 
	fetus: human 
	is_person: human ⟶ prop 
	has_rights: human ⟶ prop 
	is_born: human ⟶ prop 
	is_conceived: human ⟶ prop 
	is_black: human ⟶ prop 
	is_caucasian: human ⟶ prop 
	def_fetus: ⊦ is_conceived fetus ∧ ¬ is_born fetus 
	def_black: ⊦ is_conceived black ∧ ¬ is_caucasian black 
	
	


// theory attack =
	tag ❙
// ❚

theory constitution_pro_choice =
	include ?background_knowledge 
	// person: ⊦ ∀[x] (is_person x ⇔ is_born x ∧ is_human x) ❙
	person: ⊦ ∀[x:human] (is_person x ⇒ is_born x) 

                                                   
theory constitution_pro_slavery =
	include ?background_knowledge 
	// person: ⊦ ∀[x] is_person x ⇔ is_conceived x ∧ is_human x ∧ ¬ is_black x ❙
	person: ⊦ ∀[x:human] (is_person x ⇒ is_caucasian x)  


theory constitution_pro_life =
	include ?background_knowledge 
	person: ⊦ ∀[x:human] (is_conceived x ⇒ is_person x) 


view constitution_pro_choice_attacks_constitution_pro_slavery : ?constitution_pro_choice  ?constitution_pro_slavery =
	include ?background_knowledge = ?background_knowledge 
	// tag ?attack ❙
	/T person = person ❙



view constitution_pro_slavery_attacks_constitution_pro_choice : ?constitution_pro_slavery  ?constitution_pro_choice =
	// tag ?attack ❙
	include ?background_knowledge = ?background_knowledge 
	/T person = person ❙



view constitution_pro_life_attacks_constitution_pro_choice : ?constitution_pro_life  ?constitution_pro_choice =
	// tag ?attack ❙
	include ?background_knowledge = ?background_knowledge 
 /T person = person ❙



view constitution_pro_life_attacks_constitution_pro_slavery : ?constitution_pro_life  ?constitution_pro_slavery =
	// tag ?attack ❙
	include ?background_knowledge = ?background_knowledge 
	/T person = person ❙



view constitution_pro_slavery_attacks_constitution_pro_life : ?constitution_pro_slavery  ?constitution_pro_life =
	// tag ?attack ❙
	include ?background_knowledge = ?background_knowledge 
	/T person = person ❙



view constitution_pro_choice_attacks_constitution_pro_life : ?constitution_pro_choice  ?constitution_pro_life =
	// tag ?attack ❙
	include ?background_knowledge = ?background_knowledge 
	/T person = person ❙



theory fourteenth_amendment =
	include ?background_knowledge
	person: ⊦ is_person black 

	
	
view fourteenth_amendment_attacks_constitution_pro_slavery : ?fourteenth_amendment  ?constitution_pro_slavery =
	// tag ?attack ❙
	include ?background_knowledge = ?background_knowledge 
	/T person = person ❙



theory legal_common_ground =
	include ?background_knowledge 
	personhood_and_rights: ⊦ ∀[x] ¬ is_person x ⇒ ¬ has_rights x 


theory dredd_scott_v_sanford =
	include ?constitution_pro_slavery 
	include ?legal_common_ground 
	blacks_have_no_rights: ⊦  ¬ has_rights black  = sketch 
									"				
								  background knowledge.def_black: Blacks are not caucasian. 
									constitution_pro_slavery.person: Whoever is not caucasian is not a person to the constitution. 
									Hence blacks are not persons to the constitution. 
									legal_common_ground.personhood_and_rights: If you're not a person then you have no rights. 
									Ergo blacks have no rights
									" 


view dredd_scott_v_sanford_attacks_constitution_pro_life : ?dredd_scott_v_sanford  ?constitution_pro_life =
	include ?background_knowledge = ?background_knowledge 
	// tag ?attack ❙
	person = person 



view dredd_scott_v_sanford_attacks_constitution_pro_choice : ?dredd_scott_v_sanford  ?constitution_pro_choice =
	include ?background_knowledge = ?background_knowledge 
	// tag ?attack ❙
	person = person 



view fourteenth_amendment_superseds_dredd_scott_v_sanford : ?dredd_scott_v_sanford  ?constitution_pro_choice =
	// tag ?attack ❙
	include ?background_knowledge = ?background_knowledge 
	/T person = person ❙




view fourteenth_amendment_superseds_dredd_scott_v_sanford : ?fourteenth_amendment  ?dredd_scott_v_sanford =
	// tag ?attack ❙
	include ?background_knowledge = ?background_knowledge 
	/T person = person ❙



// view constitution_pro_choice_attacks_dredd_scott_v_sanford : ?constitution_pro_choice → ?dredd_scott_v_sanford =
	include ?background_knowledge = ?background_knowledge ❙
	// tag ?attack ❙
	/T person1 = person1 ❙
	/T person2 = person2 ❙


theory roe_v_wade =
	include ?constitution_pro_choice 
	include ?legal_common_ground 
	fetusses_have_no_rights: ⊦ ¬ has_rights fetus  = sketch 
									"				
								  background knowledge.def_fetus: fetusses are not born. 
									constitution_pro_slavery.person: Whoever is not born is not a person to the constitution. 
									Hence fetusses are not persons to the constitution. 
									legal_common_ground.personhood_and_rights: If you're not a person then you have no rights. 
									Ergo fetusses have no rights
									" 



view if_not_dredd_scott_v_sanford_then_not_roe_v_wade : ?dredd_scott_v_sanford  ?roe_v_wade =
	include ?background_knowledge = ?background_knowledge 
	black = fetus 
	blacks_have_no_rights = fetusses_have_no_rights 
	/T person1=person1 ❙
	/T person2=person2 ❙


view roe_v_wade_attacks_constitution_pro_life : ?roe_v_wade  ?constitution_pro_life =
	include ?background_knowledge = ?background_knowledge 
	// tag ?attack ❙
	person = person 


namespace http://mathhub.info/ALMANAC/JLogic/Context_Graph
import found http://mathhub.info/MitM/Foundation 

fixmeta found:?NaturalDeduction 

theory Lexicon =
example :  type 
Tweety_example : example 
Meta_Tweety_example : example 
have : example ⟶ prop 
use : example ⟶ prop 
standard : example ⟶ prop 
better_than : example ⟶ example ⟶ prop # 1 better 2 
met : example ⟶ prop  /T should be meta but unfortunately meta is an mmt keyword, hence not usable.❙
too_complicated : example ⟶ prop 




theory Knowledge_Base =
include ?Lexicon 
a : ⊦ have Tweety_example 
b : ⊦ have Meta_Tweety_example 
ax1 : ⊦ (¬ ∃[x] x better Tweety_example) ⇒ use Tweety_example 
ax2 : ⊦ met Meta_Tweety_example
ax3: ⊦ standard Tweety_example 
ax4 :  ⊦ (∃[x] x better Tweety_example) ⇒ ¬ use Tweety_example 


theory Use_Tweety =
include ?Knowledge_Base 
c: ⊦ use Tweety_example 


theory Not_Tweety =
include ?Knowledge_Base 
d: ⊦ ¬ use Tweety_example 


// theory Joint_Inconsistency =
include ?Use_Tweety ❙
include ?Not_Tweety ❙


theory Proposition =
proposition : prop


theory Pro =
include ?Proposition 
pro: ⊦ proposition 


theory Con =
include ?Proposition 
con:  ⊦ ¬ proposition 


// view Contradiction : ?Conflict_Theory → ?Joint_Inconsistency =
conflict = fals_introduction c d ❙


view prop_Tweety : ?Proposition  ?Lexicon =
proposition = use Tweety_example 


view pro_Tweety : ?Pro  ?Joint_Inconsistency =
include ?prop_Tweety
pro = c 


view con_Tweety : ?Con  ?Joint_Inconsistency =
include ?prop_Tweety 
con = d 

namespace latin:/algebraic

fixmeta latin:/?SFOLEQND

theory AdditiveSet = 
  structure add : ?Set


theory AdditiveMagma = 
  include ?AdditiveSet
  structure add : ?Magma =
    include ?AdditiveSet/add
    op # 1 + 2 prec 40
  


theory AdditiveCommutative = 
  include ?AdditiveMagma 
  structure add : ?Commutative =
    include ?AdditiveMagma/add
  


theory AdditiveIdempotent = 
  include ?AdditiveMagma 
  structure add : ?Idempotent =
    include ?AdditiveMagma/add
  


theory AdditiveSemigroup = 
  include ?AdditiveMagma
  structure add : ?Semigroup =
    include ?AdditiveMagma/add
  


theory AdditiveCommSemigroup = 
  include ?AdditiveSemigroup
  include ?AdditiveCommutative
  structure add : ?CommSemigroup =
    include ?AdditiveSemigroup/add
    include ?AdditiveCommutative/add
  

namespace latin:/algebraic

/T regular bands and views between them
mostly following the wikipedia page on Bands

Notes: 
- some names that were not given on Wikipedia are made up
- most views do not actually use (all of) the Band properties
- LeftX and RightX are stronger than X, not weaker


fixmeta ur:/?LF 

theory Magma =
  include ☞latin:/?EqualityType
  op : carrier ⟶ carrier ⟶ carrier # 1  2 prec 50


theory Semigroup =
  include ?Magma
  assoc: {x,y,z} (x∘y)∘z = x∘(y∘z)
  
  assocR: {x,y,z} x∘(y∘z) = (x∘y)∘z
        = [x,y,z] sym assoc

  assoc4:  {w,x,y,z} ((w∘x)∘y)∘z = w∘(x∘(y∘z))
        =  [w,x,y,z] trans3 (assoc congT [u]u∘z) assoc (assoc congT [u]w∘u)
  assoc4R: {w,x,y,z} w∘(x∘(y∘z)) = ((w∘x)∘y)∘z
        = [w,x,y,z] sym assoc4
  assoc5: {v,w,x,y,z} (((v∘w)∘x)∘y)∘z = v∘(w∘(x∘(y∘z)))
        = [v,w,x,y,z] trans4 (assoc4 congT [u]u∘z) assoc
                              (assoc congT [u]v∘u) (assoc congT [u]v∘(w∘u))


theory Commutative =
  include ?Magma
  comm: {x,y} x∘y = y∘x


theory Neutral =
  include ?Magma
  e  : carrier   
  neutLeft: {x} e∘x = x
  neutRight: {x} x∘e = x


theory Idempotent =
  include ?Magma
  idempotent: {x} x∘x = x


theory Monoid =
  include ?Semigroup
  include ?Neutral


theory CommSemigroup =
  include ?Semigroup
  include ?Commutative


theory Band =
  include ?Semigroup
  include ?Idempotent


theory CommMonoid =
  include ?Monoid
  include ?CommSemigroup


theory Semilattice =
  include ?Band
  include ?CommSemigroup


theory BoundedSemilattice =
  include ?Semilattice
  include ?CommMonoid


theory Regular =
	include ?Band
  regular: {x,y,z} z∘x∘z∘y∘z = z∘x∘y∘z 


theory LeftNormal =
	include ?Band
  leftregular1: {x,y,z} z∘x∘z∘y = z∘x∘y 


theory LeftRegular =
	include ?Band
  leftregular: {x,z} z∘x∘z = z∘x 


theory RightNormal =
	include ?Band
  rightregular1: {x,y,z} x∘z∘y∘z = x∘y∘z 


theory RightRegular =
	include ?Band
  rightregular: {y,z} z∘y∘z = y∘z 


/T views for the three stages of regular band theories ❚

implicit view Regular2LeftNormal : ?Regular -> ?LeftNormal =
  include ?Band
	regular = [x,y,z] leftregular1 congT [u]u∘z


implicit view LeftNormal2LeftRegular : ?LeftNormal -> ?LeftRegular =
  include ?Band
	leftregular1 = [x,y,z] leftregular congT [u]u∘y


implicit view Regular2RightNormal : ?Regular -> ?RightNormal =
  include ?Band
	regular = [x,y,z] trans3 assoc5 ((trans3 assoc4R rightregular1 assoc) congT [u]z∘u) assoc4R


implicit view RightNormal2RightRegular : ?RightNormal -> ?RightRegular =
  include ?Band
	rightregular1 = [x,y,z] trans3 assoc4 ((trans assocR rightregular) congT [u] x∘u) assocR


/T normal bands ❚

theory Normal =
	include ?Band
  normal: {x,y,z} z∘(x∘y)∘z = z∘(y∘x)∘z 


theory RightCommutative =
	include ?Band
  leftnormal: {x,y,z} z∘(x∘y) = z∘(y∘x) 


theory LeftCommutative =
	include ?Band
  rightnormal: {x,y,z} (x∘y)∘z = (y∘x)∘z 


/T views for the diamond of normal band theories (with semilattices at the bottom) ❚

implicit view Normal2RightCommutative : ?Normal -> ?RightCommutative =
  include ?Band
	normal = [x,y,z] leftnormal congT [u]u∘z


implicit view Normal2LeftCommutative : ?Normal -> ?LeftCommutative =
  include ?Band
	normal = [x,y,z] trans3 assoc (rightnormal congT [u]z∘u) assocR


view RightCommutative2Semilattice : ?RightCommutative -> ?Semilattice =
  include ?Band
	leftnormal = [x,y,z] comm congT [u]z∘u


implicit view LeftCommutative2Semilattice : ?LeftCommutative -> ?Semilattice =
  include ?Band
	rightnormal = [x,y,z] comm congT [u]u∘z


/T views from regular to normal band theories ❚

implicit view LeftNormal2Normal : ?LeftNormal -> ?Normal =
  include ?Band
  // zxzy = zxzyzxzy = zx yz zxzy = zxy zx zy = zxy xz zy = zxy zxy = zxy❙
  leftregular1 = [x,y,z] trans3 (sym idempotent) _ idempotent


implicit view LeftRegular2RightCommutative : ?LeftRegular -> ?RightCommutative =
  include ?Band
	leftregular = [x,z] trans4 assoc leftnormal assocR (idempotent congT [u]u∘x)


implicit view RightNormal2Normal : ?RightNormal -> ?Normal =
  include ?Band
  // xzyz = xzyz xzyz = x yz zxzyz = xy zxzyz = xyz zx yz = xyz xyz = xyz❙
	rightregular1 = [x,y,z] trans3 (sym idempotent) _ idempotent


implicit view RightRegular2LeftCommutative : ?RightRegular -> ?LeftCommutative =
  include ?Band
	rightregular = [y,z] trans3 rightnormal assoc (idempotent congT [u]y∘u)


/T rectangular bands (the axioms here already imply idempotency)❚

theory Rectangular =
	include ?Band
  rectangular: {x,y} x∘y∘x = x 
  
  // provable ❙
  rectangularAny: {x,y,z} x∘y∘z = x∘z


theory LeftZero =
	include ?Band
  leftsingular: {x,y} x∘y = x 


theory RightZero =
	include ?Band
  rightsingular: {x,y} x∘y = y 

namespace latin:/algebraic

/T regular bands and views between them
mostly following the wikipedia page on Bands

Notes: 
- some names that were not given on Wikipedia are made up
- most views do not actually use (all of) the Band properties
- LeftX and RightX are stronger than X, not weaker


fixmeta latin:/?SFOLEQND

theory Regular =
	include ?Band 
  regular: {x,y,z} ⊦ z∘x∘z∘y∘z ≐ z∘x∘y∘z 


theory LeftNormal =
	include ?Band 
  leftregular1: {x,y,z} ⊦ z∘x∘z∘y ≐ z∘x∘y 


theory LeftRegular =
	include ?Band 
  leftregular: {x,z} ⊦ z∘x∘z ≐ z∘x 


theory RightNormal =
	include ?Band 
  rightregular1: {x,y,z} ⊦ x∘z∘y∘z ≐ x∘y∘z 


theory RightRegular =
	include ?Band 
  rightregular: {y,z} ⊦ z∘y∘z ≐ y∘z 


/T views for the three stages of regular band theories ❚

implicit view Regular2LeftNormal : ?Regular -> ?LeftNormal =
  include ?Band
	regular = [x,y,z] leftregular1 congT [u]u∘z


implicit view LeftNormal2LeftRegular : ?LeftNormal -> ?LeftRegular =
  include ?Band
	leftregular1 = [x,y,z] leftregular congT [u]u∘y


implicit view Regular2RightNormal : ?Regular -> ?RightNormal =
  include ?Band
	regular = [x,y,z] trans3 assoc5 ((trans3 assoc4R rightregular1 assoc) congT [u]z∘u) assoc4R


implicit view RightNormal2RightRegular : ?RightNormal -> ?RightRegular =
  include ?Band
	rightregular1 = [x,y,z] trans3 assoc4 ((assocR trans rightregular) congT [u] x∘u) assocR


/T normal bands ❚

theory Normal =
	include ?Band 
  normal: {x,y,z} ⊦ z∘(x∘y)∘z ≐ z∘(y∘x)∘z 


theory RightCommutative =
	include ?Band 
  leftnormal: {x,y,z} ⊦ z∘(x∘y) ≐ z∘(y∘x) 


theory LeftCommutative =
	include ?Band 
  rightnormal: {x,y,z} ⊦ (x∘y)∘z ≐ (y∘x)∘z 


/T views for the diamond of normal band theories (with semilattices at the bottom) ❚

implicit view Normal2RightCommutative : ?Normal -> ?RightCommutative =
  include ?Band
	normal = [x,y,z] leftnormal congT [u]u∘z


implicit view Normal2LeftCommutative : ?Normal -> ?LeftCommutative =
  include ?Band
	normal = [x,y,z] trans3 assoc (rightnormal congT [u]z∘u) assocR


view RightCommutative2Semilattice : ?RightCommutative -> ?Semilattice =
  include ?Band
	leftnormal = [x,y,z] comm congT [u]z∘u


implicit view LeftCommutative2Semilattice : ?LeftCommutative -> ?Semilattice =
  include ?Band
	rightnormal = [x,y,z] comm congT [u]u∘z


/T views from regular to normal band theories ❚

implicit view LeftNormal2Normal : ?LeftNormal -> ?Normal =
  include ?Band
  // zxzy = zxzyzxzy = zx yz zxzy = zxy zx zy = zxy xz zy = zxy zxy = zxy❙
  leftregular1 = [x,y,z] trans3 (idem sym) _ idem


implicit view LeftRegular2RightCommutative : ?LeftRegular -> ?RightCommutative =
  include ?Band
	leftregular = [x,z] trans4 assoc leftnormal assocR (idem congT [u]u∘x)


implicit view RightNormal2Normal : ?RightNormal -> ?Normal =
  include ?Band
  // xzyz = xzyz xzyz = x yz zxzyz = xy zxzyz = xyz zx yz = xyz xyz = xyz❙
	rightregular1 = [x,y,z] trans3 (idem sym) _ idem


implicit view RightRegular2LeftCommutative : ?RightRegular -> ?LeftCommutative =
  include ?Band
	rightregular = [y,z] trans3 rightnormal assoc (idem congT [u]y∘u)


/T rectangular bands (the axioms here already imply idempotency)❚

theory Rectangular =
	include ?Band 
  rectangular: {x,y} ⊦ x∘y∘x ≐ x 
  
  // provable ❙
  rectangularAny: {x,y,z} ⊦ x∘y∘z ≐ x∘z


theory LeftZero =
	include ?Band 
  leftzero: {x,y} ⊦ x∘y ≐ x 


theory RightZero =
	include ?Band 
  rightzero: {x,y} ⊦ x∘y ≐ y 

namespace latin:/algebraic

fixmeta powertypes?PowerSFOL

theory GeneratedSets = 
  include ?Set
  structure generated : latin:/?ClosureOperator = 
    X = universe
    closure #  1  prec 10
  


theory GeneratedMagmas =
  include ?Magma
  include ?GeneratedSets
  closure_op: {S} ⊦ ∀[x]∀[y] x∈⟨S⟩ ⇒ y∈⟨S⟩ ⇒ (x∘y)∈⟨S⟩ 


theory GeneratedPointed =
  include ?Pointed
  include ?GeneratedMagmas
  closure_elem: {S} ⊦ e∈⟨S⟩ 


theory GeneratedInverseFun =
  include ?InverseFun
  include ?GeneratedPointed
  closure_inv: {S} ⊦ ∀[x] x∈⟨S⟩ ⇒ x⁻∈⟨S⟩ 

namespace latin:/algebraic

fixmeta latin:/?SFOLEQ 

theory Quasigroup = 
  include ?Magma 
  div_left : ⊦ ∀[x] ∀[y] ∃[a] (a∘x ≐ y) 
  div_right: ⊦ ∀[x] ∀[y] ∃[b] (x∘b ≐ y)  


theory Loop = 
  include ?Quasigroup 
  include ?Monoid


theory InverseOperator = 
  include ?Semigroup
  inv : U ⟶ U# 1  prec 60
  is_weak_inverse : U ⟶ U ⟶ prop
                  = [x,y] x∘y∘x ≐ x ∧ y∘x∘y ≐ y# %n 1 2 prec 30


/T weaker variant of unique inverse element, formulated without neutral element
   usually union of X and WeakInverse usually called InverseX in the literature❚
theory WeakInverse = 
  include ?InverseOperator
  weak_inverse : ⊦ ∀[x] is_weak_inverse x (x⁻)


theory InverseFun = 
  include ?Monoid
  include ?InverseOperator

  inverseLeft:  ⊦ ∀[x] x⁻∘x ≐ e
  inverseRight: ⊦ ∀[x] x∘x⁻ ≐ e
  
  div : U ⟶ U ⟶ U= [x,y]x∘y⁻
  
  invL : {x} ⊦ x⁻∘x≐e= [x] inverseLeft forallE x
  invR : {x} ⊦ x∘x⁻≐e= [x] inverseRight forallE x
  
  inverse_inv : {x} ⊦ inverse x (x⁻)= [x] andI invR invL
  inv_unit : ⊦ e⁻≐e = inverse_unique inverse_inv inverse_neutral
  inv_op : {x,y} ⊦ (x∘y)⁻ ≐ y⁻∘x⁻
         = [x,y] inverse_unique inverse_inv (inverse_op inverse_inv inverse_inv)


theory InverseExistence = 
  include ?Monoid 
  inverseLeft:  ⊦ ∀[x]∃[i] i∘x ≐ e 
  inverseRight: ⊦ ∀[x]∃[i] x∘i ≐ e 


theory Group = 
  include ?Monoid 
  include ?InverseFun 


theory CommGroup = 
  include ?Group
  include ?CommMonoid


theory GroupHom = 
  include ?MagmaHom 
  structure domain : ?Group =
    U = domain/U 
  
  structure codoamin : ?Group = 
    U = codomain/U 
  
  // e: ⊦ U domain/e ≐ codomain/e ❙

namespace latin:/algebraic

fixmeta latin:/?SFOLEQND

theory Magma = 
  include ?Set 
  op : U ⟶ U ⟶ U # 1  2 prec 50
  
  total structure divisibility : ?Relation =
    include ?Set
    rel = [x,z] ∃[y]x∘y≐z
  


theory MagmaHom = 
  include ?SetHom 
  structure domain : ?Magma =
    include ?SetHom/domain
  
  structure codomain : ?Magma = 
    include ?SetHom/codomain
  
  op : ⊦ ∀[x]∀[y] U (x domain/∘ y) ≐ U x codomain/∘ U y 


theory SubMagma = 
  include ?SubSet
  structure parent : ?Magma =
    include ?SubSet/parent
  
  op: ⊦ ∀[x]∀[y] U x ⇒ U y ⇒ U (x parent/∘ y)  


theory Commutative = 
  include ?Magma 
  comm_ax : ⊦ ∀[x]∀[y] x∘y ≐ y∘x
  comm : {x,y} ⊦ x∘y ≐ y∘x = [x,y] comm_ax forallE x forallE y


view OppositeMagma : ?Magma  ?Magma = 
  universe = universe 
  U = U 
  op = [x, y] y ∘ x 


theory Idempotent = 
  include ?Magma 
  idem_ax: ⊦ ∀[x] x∘x ≐ x 
  idem : {x} ⊦ x∘x≐x = [x] idem_ax forallE x


view OppositeCommMagma : ?Commutative  ?Commutative =
  include ?OppositeMagma 
  op = op 
  comm_ax = comm_ax 


theory PowerAssociative = 
  include ?Magma 
  power_assoc : ⊦ ∀[x] (x∘x)∘x ≐ x∘(x∘x)


theory Semigroup = 
  include ?Magma 
  assoc_ax : ⊦ ∀[x]∀[y]∀[z] (x∘y)∘z ≐ x∘(y∘z)
  
  assoc: {x,y,z} ⊦ (x∘y)∘z ≐ x∘(y∘z)
       = [x,y,z] assoc_ax forallE x forallE y forallE z
  assocR: {x,y,z} ⊦ x∘(y∘z) ≐ (x∘y)∘z
        = [x,y,z] assoc sym
  assoc4:  {w,x,y,z} ⊦ ((w∘x)∘y)∘z ≐ w∘(x∘(y∘z))
        =  [w,x,y,z] trans3 (assoc congT [u]u∘z) assoc (assoc congT [u]w∘u)
  assoc4R: {w,x,y,z} ⊦ w∘(x∘(y∘z)) ≐ ((w∘x)∘y)∘z
          = [w,x,y,z] assoc4 sym
  assoc5: {v,w,x,y,z} ⊦ (((v∘w)∘x)∘y)∘z ≐ v∘(w∘(x∘(y∘z)))
        = [v,w,x,y,z] trans4 (assoc4 congT [u]u∘z) assoc
                             (assoc congT [u]v∘u) (assoc congT [u]v∘(w∘u))
  
  realize ?PowerAssociative
  power_assoc = forallI [x] assoc
  
//  total structure divisibility : ?Transitivity =
    include ?Magma/divisibility❙
//    metarel/trans = [x,y,z,p,q] p existsE [xy,xyP] q existsE [yz,yzP]
      existsI (xy ∘ yz) trans3 assocR (xyP congT [u]u∘yz) yzP❙
//  ❚


view OppositeSemigroup : ?Semigroup  ?Semigroup = 
  include ?OppositeMagma 
  op = op 
  assoc_ax = assoc_ax


theory CommSemigroup = 
  include ?Semigroup 
  include ?Commutative 


theory Band = 
  include ?Semigroup 
  include ?Idempotent 


theory CommIdempotent =
  include ?Idempotent
  include ?Commutative


theory Semilattice = 
  include ?CommSemigroup
  include ?Band
  include ?CommIdempotent


theory Pointed = 
  include ?Set
  elem : U


theory UnitElement =
  include ?Magma
  structure unitelem : ?Pointed =
    include ?Set
    elem # e
  
  involution : U ⟶ prop = [x] x∘x≐e


theory RightUnital =
  include ?UnitElement
  neutralR : ⊦ ∀[x] x∘e ≐ x
  neutR: {x} ⊦ x∘e≐x= [x] neutralR forallE xrole Simplify


theory LeftUnital = 
  include ?UnitElement
  neutralL : ⊦ ∀[x] e∘x ≐ x
  neutL: {x} ⊦ e∘x≐x= [x] neutralL forallE x role Simplify 


theory Unital = 
  include ?LeftUnital 
  include ?RightUnital 


theory AbsorbingElement =
  include ?Magma
  structure absorbingelem : ?Pointed =
    include ?Set
    elem # abs
  


theory RightAbsorptive =
  include ?AbsorbingElement
  absorbR : ⊦ ∀[x] x∘abs ≐ abs
  absR : {x} ⊦ x∘abs ≐ abs = [x] absorbR forallE xrole Simplify


theory LeftAbsorptive =
  include ?AbsorbingElement
  absorbL : ⊦ ∀[x] abs∘x ≐ abs
  absL : {x} ⊦ abs∘x ≐ abs = [x] absorbL forallE xrole Simplify


theory Absorptive = 
  include ?LeftAbsorptive
  include ?RightAbsorptive


theory FirstNonNeutral =
  include ?Unital
  firstNonNeutral : ⊦ ∀[x] x≠e ⇒ ∀[y]x∘y≐x  
  // realize ?Monoid❙


theory LastNonNeutral =
  include ?Unital
  lastNonNeutral : ⊦ ∀[x] x≠e ⇒ ∀[y]x∘y≐x  
  // realize ?Monoid❙


theory Powers = 
  include ?PowerAssociative
  include ?Unital
  include ☞latin:/?Nat
  power : U ⟶ ℕ ⟶ U# 1 ^ 2 prec 60
  power_zero: {x} ⊦ x^0 ≐ e role Simplify
  power_succ: {x,n} ⊦ x^(n') ≐ x^n∘x role Simplify


theory Monoid = 
  include ?Semigroup
  include ?Unital

  inverse : U ⟶ U ⟶ prop = [x,xˈ] x∘xˈ≐e ∧ xˈ∘x≐e# inverse 1 2 prec 30

  inverse_sym : {x,xˈ} ⊦ inverse x xˈ ⟶ ⊦ inverse xˈ x
              = [x,xˈ,p] andI (p andEr) (p andEl)
  inverse_unique : {x,x1,x2} ⊦ inverse x x1 ⟶ ⊦ inverse x x2 ⟶ ⊦ x1≐x2
                 = [x,x1,x2,p,q] trans3
                   ((neutR sym) trans (q andEl sym congT [u]x1∘u))
                   assocR
                   ((p andEr congT [u]u∘x2) trans neutL)

  inverse_neutral : ⊦ inverse e e
                  = andI neutL neutL
  inverse_op : {x,y,xˈ,yˈ} ⊦ inverse x xˈ ⟶ ⊦ inverse y yˈ ⟶ ⊦ inverse (x∘y) (yˈ∘xˈ)
             = [x,y,xˈ,yˈ,p,q] andI
             (trans3 assoc ((trans3 assocR (q andEl congT [u]u∘xˈ) neutL) congT [u]x∘u) (p andEl))
             (trans3 assoc ((trans3 assocR (p andEr congT [u]u∘y) neutL) congT [u]yˈ∘u) (q andEr))
             

  involution_inverse: {x} ⊦ involution x ⇔ inverse x x
             = [x] equivI ([p] andI p p) ([p] p andEl)


theory Involutory =
  include ?Monoid
  involutory: {x} ⊦ involution x
  
  inverse_refl : {x} ⊦ inverse x x
               = [x] involution_inverse equivEl involutory
  inverse_ident : {x,y} ⊦ inverse x y ⟶ ⊦ x≐y
                = [x,y,p] inverse_unique inverse_refl p


theory IdempotentMonoid = 
  include ?Monoid
  include ?Band


theory CommMonoid = 
  include ?Monoid
  include ?CommSemigroup


theory BoundedSemilattice =
  include ?Semilattice 
  include ?CommMonoid 

namespace latin:/algebraic

fixmeta latin:/powertypes?PowerSFOL 

theory LeftModule = 
	include ?CommGroup 
  structure left_scalars : ?Ring =
	  U # S 
	

	left_scalar_mult : S ⟶ U ⟶ U # 1  2 prec 60
	left_identity: ⊦ ∀[a:U] one ∗ a ≐ a 
	left_distrib_ring: ⊦ ∀[r: S] ∀[s: S] ∀[a : U] (r + s) ∗ a ≐ add (r ∗ a) (s ∗ a)  
	left_distrib_module: ⊦ ∀[r: S] ∀[a: U] ∀[b: U] r ∗ (add a b) ≐ add (r ∗ a) (r ∗ b) 
	left_assoc_ring: ⊦ ∀[r: S] ∀[s: S] ∀[a: U] r ∗ (s ∗ a) ≐ (r ⋅ s) ∗ a 


theory RightModule = 
	include ?CommGroup 
  structure right_scalars : ?Ring =
	  U # S 
	

	right_scalar_mult : U ⟶ S ⟶ U # 1  2 prec 60
	right_identity: ⊦ ∀[a:U] a ∗ one ≐ a 
	right_distrib_ring: ⊦ ∀[r: S] ∀[s: S] ∀[a : U] a ∗ (r + s) ≐ add (a ∗ r) (a ∗ s)  
	right_distrib_module: ⊦ ∀[r: S] ∀[a: U] ∀[b: U] (add a b) ∗ r ≐ add (a ∗ r) (b ∗ r) 
	right_assoc_ring: ⊦ ∀[r: S] ∀[s: S] ∀[a: U] (a ∗ s) ∗ r ≐ a ∗ (s ⋅ r) 


theory BiModule = 
  include ?LeftModule 
  include ?RightModule 


theory VectorSpace = 
  include ?LeftModule 
  structure scalars : ?DivisionRing =
    include ?LeftModule/left_scalars 
  

namespace latin:/algebraic

fixmeta latin:/?SFOLEQND

theory Relation = 
  include ?Set
  rel : U ⟶ U ⟶ prop# 1 $ 2 prec 30
  structure metarel : latin:/?Relation =
    carrier = U
    rel = [x,y] ⊦ x $ y
  


theory Reflexivity =
  include ?Relation
  structure metarel : latin:/?Reflexivity =
    include ?Relation/metarel
  


theory Symmetry =
  include ?Relation
  structure metarel : latin:/?Symmetry =
    include ?Relation/metarel
  


theory Transitivity =
  include ?Relation
  structure metarel : latin:/?Transitivity =
    include ?Relation/metarel
  


theory Preorder =
  include ?Reflexivity
  include ?Transitivity


theory EquivalenceRelation =
  include ?Preorder
  include ?Symmetry


theory AntiSymmetry =
  include ?Relation
  antisym : {x,y} ⊦ x$y ⟶ ⊦ y$x ⟶ ⊦ x≐y


theory Order =
  include ?Preorder
  include ?AntiSymmetry

namespace latin:/algebraic 

fixmeta latin:/?SFOLEQ 

theory BiMagma = 
  include ?Set 
  structure add : ?Magma = 
    universe = universe 
    U = U 
    op # 1 + 2 prec 40 
  
  
  structure mult : ?Magma = 
    universe = universe 
    U = U 
    op # 1  2 prec 50 
  


theory Ringoid =
  include ?BiMagma 
  left_distrib: ⊦ ∀[r]∀[x]∀[y] r⋅(x+y) ≐ r⋅x + r⋅y 
  right_distrib: ⊦ ∀[r]∀[x]∀[y] (x+y)⋅r ≐ x⋅r + y⋅r 


theory CommRingoid =
  include ?Ringoid 
  structure mult : ?CommSemigroup =
    include ?BiMagma/mult 
  


theory MonoidalRingoid =
  include ?Ringoid
  structure add : ?Monoid = 
    include ?BiMagma?add
    elem # zero
  


theory BiMonoid =
  include ?MonoidalRingoid
  structure mult : ?Monoid = 
    include ?BiMagma?mult
    elem # one
  


theory NonZeroInvertible =
  include ?BiMonoid
  multinverse : ⊦ ∀[x] ¬x≐zero ⇒ ∃[y] mult/inverse x y


theory NoZeroDividers =  
  include ?BiMonoid 
  no_zero_div: ⊦ ∀[x]∀[y] (x⋅y ≐ zero) ⇒ ((x ≐ zero) ∨ (y ≐ zero)) 


theory NonTrivial =
  include ?BiMonoid
  neq01: ⊦ ¬(zero ≐ one)


theory Semiring = 
	include ?BiMonoid
	structure add : ?CommMonoid =                                                                   
	  include ?MonoidalRingoid/add 
	


theory CommSemiring = 
  include ?Semiring 
  include ?CommRingoid 


theory NearRing = 
  include ?BiMonoid
  structure add : ?Group =
    include ?MonoidalRingoid/add 
    inv # - 1 prec 45
    div # 1 - 2 prec 40
  


theory CommNearRing = 
  include ?NearRing 
  include ?CommRingoid 


theory Ring = 
  include ?NearRing
  // realize ?Semiring❙
  structure add : ?CommGroup =
    include ?NearRing/add 
  


theory BooleanRing = 
  include ?Ring 
  structure mult : ?IdempotentMonoid =
    include ?BiMonoid/mult
  


theory CommRing = 
  include ?Ring 
  include ?CommRingoid 


theory IntegralDomain =  
  include ?CommRing 
  include ?NoZeroDividers


theory SkewField = 
  include ?Ring 
  include ?NonZeroInvertible
  include ?NonTrivial


theory Field = 
  include ?SkewField 
  include ?CommRingoid 


theory BilinearRingoid = 
  include ?Ringoid 
  f: U ⟶ U ⟶ U 
  bilinear: ⊦ ∀[x]∀[y]∀[z] (f (x+y) z) ≐ (f x z) + (f y z) ∧ (f x (y+z)) ≐ (f x y) + (f y z) 
  homogen: ⊦ ∀[r]∀[x]∀[y] f (r⋅x) y ≐ r⋅ (f x y) ∧ f x (r⋅y) ≐ r⋅(f x y) 


theory LieRing =
  include ?Ring
  include ?BilinearRingoid 

  bracket = f #  1  2  prec 40  
  bracket_defn: ⊦ ∀[x]∀[y] ⟨x y⟩ ≐ x⋅y - y⋅x 
  jacobi: ⊦ ∀[x]∀[y]∀[z] ⟨x ⟨y z⟩⟩ + ⟨y ⟨z x⟩⟩ + ⟨z ⟨x y⟩⟩ ≐ zero 
  alternating: ⊦ ∀[x] ⟨x x⟩ ≐ zero 

namespace latin:/algebraic

fixmeta latin:/?SFOLEQND

theory Set = 
  universe : tp
  U = tm universe


theory SetHom = 
   structure domain : ?Set
   structure codomain : ?Set
   U : domain/U ⟶ codomain/U 


theory SubSet = 
  structure parent : ?Set =
    U # P
  
  universe : P ⟶ prop# U 1 prec 40

namespace latin:/

fixmeta ur:?LF

view PropositionsAsTypes : ?Logic  ?TypedTerms =
  prop = tp
  ded  = tm


view TypesAsPropositionsAs : ?TypedTerms  ?Logic =
  tp = prop
  tm = ded

namespace latin:/

fixmeta ur:?LF

theory Propositions =
  prop  : type


theory Proofs =
  include ?Propositions
  ded   : prop ⟶ type#  1  prec -5role Judgment
  
  inconsistent : type= {a} ⊦ a# role Judgment
  inconsistentE : inconsistent ⟶ {a} ⊦ a= [p,a] p a# 1 inconE %I2


theory Logic =
  include ?Propositions
  include ?Proofs


theory Terms =
  term : type


theory Types =
  tp: type


theory Kinds =
  kd : type


theory TypedTerms =
  include ?Types
  tm: tp ⟶ type# tm 1 prec -5


theory SoftTypedTerms =
  include ?Terms
  include ?Types
  include ?Propositions
  of : term ⟶ tp ⟶ prop# 1  2 prec 30


theory KindedTypes =
  include ?Kinds
  tf : kd ⟶ type# tf 1 prec -5
  tpk : kd
  realize ?Types
  tp = tf tpk


theory UntypedLogic =
  include ?Logic
  include ?Terms


theory TypedLogic =
  include ?Logic
  include ?TypedTerms


theory SoftTypedLogic =
  include ?SoftTypedTerms
  include ?Logic
         

theory InternalPropositions =
  include ?TypedTerms
  bool: tp
  realize ?Propositions
  prop = tm bool


theory InternalLogic =
  include ?InternalPropositions
  include ?Proofs


theory InternalTypes =
  include ?UntypedLogic
  in : term ⟶ term ⟶ prop# 1  2 prec 30
  realize ?SoftTypedTerms
  tp = term
  of = in
  
  total structure typesAsPredicates : ?SoftTypedTerms =
    include ?Terms
    include ?Propositions
    tp = term ⟶ prop
    of = [X,A] A X
  

namespace latin:/

fixmeta ur:?LF

theory Equality =
  include ?UntypedLogic
  equal : term ⟶ term ⟶ prop# 1  2 prec 30role Eq


theory EqualityND =
  include ?Equality
  refl  : {x} ⊦ x ≐ x# refl %I1
  congP : {x,y} ⊦ x ≐ y ⟶ {P: term ⟶ prop} ⊦ P x ⟶ ⊦ P y# 3 congP 4 5
  
  total structure eq : ?EquivalenceCongruence =
    carrier = term
    rel = [x,y] ⊦ x≐y
    refl = [x] refl
    sym = [x,y,p] p congP ([u]u≐x) refl
    trans = [x,y,z,p,q] q congP ([u]x≐u) p
    congT = [x,y,p,T] p congP ([u] T x ≐ T u) refl
  


theory SoftTypedEquality =
  include ?SoftTypedLogic
  include ?Equality


theory SoftTypedEqualityND =
  include ?SoftTypedLogic
  include ?EqualityND


theory TypedEquality =
  include ?TypedLogic
  equal  : {A} tm A ⟶ tm A ⟶ prop# 2  3 prec 30role Eq


theory TypedEqualityND =
  include ?TypedEquality
  refl   : {A,x: tm A} ⊦ x ≐ x
  congP  : {A,  x,y} ⊦ x ≐ y ⟶ {P: tm A ⟶ prop} ⊦ P x ⟶ ⊦ P y# 4 congP 5 6
  congT  : {A,B,x,y} ⊦ x ≐ y ⟶ {T: tm A ⟶ tm B} ⊦ T x  ≐  T y # 5 congT 6
         = [A,B,x,y,p,T] p congP ([u] T x ≐ T u) refl
  
  sym    : {A, x,y: tm A} ⊦ x ≐ y ⟶ ⊦ y ≐ x# 4 sym
         = [A,x,y,p] p congP ([u]u≐x) refl
  trans  : {A, x,y,z: tm A} ⊦ x ≐ y ⟶ ⊦ y ≐ z ⟶ ⊦ x ≐ z# 5 trans 6
         = [A,x,y,z,p,q] q congP ([u]x≐u) p
  trans3 : {A, w,x,y,z: tm A} ⊦ w ≐ x ⟶ ⊦ x ≐ y ⟶ ⊦ y ≐ z ⟶ ⊦ w ≐ z
         = [A, w,x,y,z,p,q,r] p trans q trans r
  trans4 : {A, v,w,x,y,z: tm A} ⊦ v ≐ w ⟶ ⊦ w ≐ x ⟶ ⊦ x ≐ y ⟶ ⊦ y ≐ z ⟶ ⊦ v ≐ z
         = [A, v,w,x,y,z,p,q,r,s] p trans q trans r trans s

namespace latin:/

fixmeta ur:?PLF

theory OneTyped =
  carrier : type

 
theory Relation =
  include ?OneTyped
  rel : carrier ⟶ carrier ⟶ type# 1 $ 2 prec 30role Judgment


theory Reflexivity =
  include ?Relation
  refl : {x} x$x


theory Symmetry =
  include ?Relation
  sym : {x,y} x$y ⟶ y$x


theory Transitivity =
  include ?Relation
  trans    : {x,y,z} x$y ⟶ y$z ⟶ x$z# 4 %n 5
  trans3   : {w,x,y,z} w$x ⟶ x$y ⟶ y$z ⟶ w$z
           = [w,x,y,z,p,q,r] p trans q trans r
  trans4   : {v,w,x,y,z} v$w ⟶ w$x ⟶ x$y ⟶ y$z ⟶ v$z
           = [v,w,x,y,z,p,q,r,s] trans3 (p trans q) r s


theory Preorder =
  include ?Reflexivity
  include ?Transitivity


theory EquivalenceRelation =
  include ?Preorder
  include ?Symmetry


theory Congruence =
  include ?Relation
  congT: {x,y} x$y ⟶ {T: carrier ⟶ carrier} T x $ T y # 3 congT 4


theory EquivalenceCongruence =
  include ?EquivalenceRelation
  include ?Congruence


/T Equality is an equivalence-congruence.
   But semantic equality is even stronger: it allows substitution in objects of any type so that equal objects can never be distinguished.
   This is different from the syntactic equality used inside a logic, where equal objets cannot be distinguished by logical formulas but might be distinguishable by other judgments.❚
theory SemanticEquality =
  include ?EquivalenceRelation
  cong : {x,y} x$y ⟶ {A: carrier ⟶ type} A x ⟶ A y# 3 cong 4 5
  // realizes Congruence❙
  congT: {x,y} x$y ⟶ {T: carrier ⟶ carrier} T x $ T y # 3 congT 4
       = [x,y,p,T] p cong ([u]T x $ T u) refl


theory EqualityType =
  include ?OneTyped
  structure equalityRel : ?EquivalenceRelation =
    include ?OneTyped
    rel # 1 = 2
    refl @ refl
    sym @ sym
    trans @ trans
    trans3 @ trans3
    trans4 @ trans4
  


theory AntiSymmetry =
  include ?EqualityType
  include ?Relation
  antisym : {x,y} x$y ⟶ y$x ⟶ x = y


theory Order =
  include ?Preorder
  include ?AntiSymmetry

namespace latin:/

fixmeta ur:?LF

theory Subtyping =
  include ?Types
  include ?Logic
  subtype : tp ⟶ tp ⟶ prop# 1  2 prec 30
  
  structure subtype_preorder : ?Preorder =
    carrier = tp
    rel = [A,B] ⊦ A⪽B
  


theory SubtypeInjections =
  include ?TypedTerms
  include ?Subtyping
  include ?TypedEquality
  
  inject : {A,B} ⊦ A ⪽ B ⟶ tm A ⟶ tm B# 4  3 prec 50
  
  inject_refl : {A,x: tm A} ⊦ x ↑ subtype_preorder/refl ≐ x
  inject_trans : {A,B,C,x: tm A,P:⊦A⪽B, Q:⊦B⪽C} ⊦ x↑(P subtype_preorder/trans Q) ≐ (x↑P)↑Q

namespace latin:/

fixmeta latin:/?SFOLEQ

theory Booleans =
  bool: tp
  
  tt: tm bool
  ff: tm bool

  if: {S} tm bool ⟶ tm S ⟶ tm S ⟶ tm S# if 2 then 3 else 4 prec 50

  bool_tnd : ⊦ ∀[b] b≐tt ∨ b≐ff
  bool_nontrivial : ⊦ ¬ tt≐ff
  
  if_tt : {s,x,y:tm s} ⊦ if tt then x else y ≐ x
  if_ff : {s,x,y:tm s} ⊦ if ff then x else y ≐ y

namespace latin:/

fixmeta ur:?LF

/T A formalization of Discourse Representation Theory (Hans Kamp \cite{Kamp:atotas81}; 
  see also \cite{KamRey:acffodrs96}).
  This formalization is patterned after https://kwarc.info/people/mkohlhase/papers/dlc00.pdf
  only that we restrict ourselves to the first-order case. 
  We give DRSes and Conditions a mode (in the type), where modes record the binding 
  and bindable (i.e. free) discourse referents. 
  In particular, the modes allow us to predict binding potentials; just see the positive 
  referents in the mode. 
  The modes have special computation rules here, so that they are normalized correctly.

  

theory DRT =
  dr: type //Discourse Referents ❙
  mode : type  //DLC modes, they annotate the dynamic status of DRs ❙
  pos: dr ⟶ mode# 1  prec 60
  neg: dr ⟶ mode# 1  prec 60
  empty : mode# 
  punion : mode ⟶ mode ⟶ mode# 1  2 prec 50

  mequal : mode ⟶ mode ⟶ type# 1  2 prec 30role Eq
  refl : {x} x ≐ x
  // bounded semi-lattice❙
  
  capture: {x} x⁺⊎x⁻ ≐ pos x //specifying DR capture ❙
  
  rule ☞scala://modes.drt.latin2?NormalizePunion
  
  close : mode ⟶ mode# 1  prec 60
  close_pos: {x} x⁺↓ ≐ ∅ role Simplify
  close_neg: {x} x⁻↓ ≐ x⁻ role Simplify
  close_empty: ∅↓ ≐ ∅ role Simplify 
  close_close: {x}x↓↓ ≐ x↓ role Simplify
  
  // normal form of modes: set of DR with function into boolean❙
  
  drs : mode ⟶ type# 1 # o prec -5 // type of DRSes ❙
  tm : mode ⟶ type# tm 1 prec -5 // type of terms ❙
  cond : mode ⟶ type# cond 1 prec -5 // type of conditions ❙
  
  /T DRSs❙
  atomic : {m,n} cond n ⟶ drs (m⊎n)# 1 | 3 prec 10  // m is just set of drs, all mapped with pos in the return type❙
  merge : {m,n} drs m ⟶ drs n ⟶ drs(m⊎n) # 1  2 
  seqmerge : {m,n} drs m ⟶ drs n ⟶ drs (m ⊎ n↓) # 1 ;; 2 

  
  /T conditions❙
  and : {m,n} cond m ⟶ cond n ⟶ cond m⊎n# 3  4 prec 20
  dneg : {m} drs m ⟶ cond m↓# ¬* 2 prec 60
  dimpl : {m,n} drs m ⟶ drs n ⟶ cond (m⊎n↓)↓ # 3 ⇒* 4 prec 20 

  /T terms❙
  idref : {i:dr} tm i⁻# ` 1 prec 60


theory Example : ?DRT =
  /T example for a predicate❙
  farmer : {m} tm m ⟶ cond m# %%prefix 1 1 prec 100
  donkey  : {m} tm m ⟶ cond m# %%prefix 1 1 prec 100
  stick  : {m} tm m ⟶ cond m# %%prefix 1 1 prec 100
  beat: {l,m,n} tm l ⟶ tm m ⟶ tm n ⟶ cond l⊎m⊎n# %%prefix 3 3 prec 100
  own: {m,n} tm m ⟶ tm n ⟶ cond m⊎n# %%prefix 2 2 prec 100
  u: dr
  v: dr
  w: dr
  uv : mode = u⁺ ⊎ v⁺
  /T A farmer owns a donkey ❙
  fod = uv | farmer`u ∧ donkey`v ∧ own(`u)`v
  /T He beats it with a stick ❙
  fbds = w⁺ | stick`w ∧ beat(`u)(`v)`w
  /T the iconic DRT example: If a farmer owns a donkey, he beats it with a stick ❙
  donkey_sentence: drs ∅ = ∅ | fod ⇒* fbds

namespace latin:/

/T Dynamic Logic is a Multi-Modal Logic originally introduced by
  Vaugham Pratt in 1996 for reasoning about imperative programs
  and later extended to more general uses in linguistics and philosophy.
  See https://en.wikipedia.org/wiki/Dynamic_logic_(modal_logic) for details.
  
  Dynamic Logic comes with a very simple non-deterministic programming
  language Π that only features composition, distribution, iteration, test, and assignment.
  
  The main idea is to have a modality for every program α and proposition A:prop
  - ⟬α⟭A means that "if α terminates, then $A$ holds afterwards"
  - ⦉α⦊A means that "α terminates and $A$ holds afterwards".
  The possible worlds are "states", i.e. variable assignments for program
  variables, and a state w:world is accessible from state v:state for program α,
  if a run of program α in v yields state w.
  
  Dynamic logic comes in three levels of modeling: 
  - Proposititional Dynamic Logic: programs are built up from program opaque variables,
    states are unspecified, and tests are over propositional formulae.
  - First-Order Dynamic Logics: program contain (program) variables and assignment,
    possible worlds are states, accessibility is state change.


fixmeta ur:?LF

theory Programs =
  prog : type# Π


/T Dynamic Logic is just the multimodal logic 
   where the modality is given by Π programs. ❚
theory DynamicLogic =
  include ?MML
  realize ?Programs
  prog = modality 


/T A simple non-deterministic programming language ❚
theory NonDetProg =
  include ?PL
  include ?Programs

  /T the programming language primitives of a non-deterministic programming
    language Π whose semantics is easy to specify.❙
  comp : Π ⟶ Π ⟶ Π# 1 ; 2 prec 5
  distrib : Π ⟶ Π ⟶ Π# 1  2 prec 30
  iteration : Π ⟶ Π# * 1 prec 60
  test : prop ⟶ Π# 1 ? prec 10

  /T in Π, we can define the usual program combinators we know and love ❙
  skip : Π = true ?
  ifte : prop ⟶ Π ⟶ Π ⟶ Π # if 1 then 2 else 3
       = [F,P,Q] (F ? ; P) ∪ (¬F ? ; Q)
  while : prop ⟶ Π ⟶ Π # while 1 do 2
        = [F,P] *(F ?;P) ; ¬F ?
  until : prop ⟶ Π ⟶ Π # repeat 2 until 1
        = [F,P] *(P; ¬F ?) ; F ?


theory PropDynamicLogic =
  include ?DynamicLogic
  include ?NonDetProg


/T A theory of (first-order) program variables and for Π; we also extend the language of
tests ot sorted first-order logic ❚
theory TypedDynamicLogic =
  include ?PropDynamicLogic
  include ?SFOLEQ
  
  var : tp ⟶ type
  
  retrieve : {S} var S ⟶ tm S# ` 2 prec 60
  
  assign  : {S} var S ⟶ tm S ⟶ Π# 2  3 prec 35
  random_assign : {S} var S ⟶ Π# randomize 2 prec 35


/T A simple example to test what we have done above ❚
theory Example : ?TypedDynamicLogic =
  include ?Booleans
  int: tp
  1:tm int
  5:tm int
  plus: tm int ⟶ tm int ⟶ tm int# 1 + 2 prec 50
  
  test: {b: var bool,x:var int}prog
      = [b,x] x≔1; b≔tt; while `b≐tt do (x ≔ `x+1; if `x≐5 then b≔ff else skip); x≔`x+1


namespace kripkemodels

/T a theory of states, i.e. assignments to program variables ❚
theory State : latin:/?HOL =
  include ?Worlds
  cell : tp ⟶ tp
  state: tm W ⟶ {S} tm cell S ⟶ tm S # 3 * 1 prec 50 
  
  extends : tm W ⟶ tm W ⟶ {S} tm cell S ⟶ (tm W ⟶ tm S) ⟶ prop
          = [v,w,S,n,x] n*w ≐ x v ∧ ∀[m] ¬n≐m ⇒ m*v≐m*w
          # extends 1 2 4 5
  
  trclos : {S} (tm S ⟶ tm S ⟶ prop) ⟶ (tm S ⟶ tm S ⟶ prop) # trclos 2 3 4
  trclose_extend : {S,r} {x,y: tm S} ⊦ r x y ⟶ ⊦ trclos r x y
  trclose_refl : {S,r} {x: tm S} ⊦ trclos r x x
  trclose_trans: {S,r} {x,y,z: tm S} ⊦ trclos r x y ⟶ ⊦ trclos r y z ⟶ ⊦ trclos r x z


view DynamicLogicSemantics : latin:/?DynamicLogic  ?State =
  include ?MMLSemantics


view NonDetProgSemantics : latin:/?NonDetProg  ?State =
  include ☞latin:/?Programs❘ = ?DynamicLogicSemantics
  include ?PLSemantics
  comp = [p,q] [u,w] ∃ [v] p u v ∧ q v w
  distrib = [p,q] [v,w] p v w ∨ q v w
  iteration = [p] [v,w] trclos p v w
  test = [f] [v,w] f v ∧ v≐w

  // check currently skipped❙
  skip = [v,w] v ≐ w


view PropDynamicLogicSemantics : latin:/?PropDynamicLogic  ?State =
  include ?DynamicLogicSemantics
  include ?NonDetProgSemantics


view TypedDynamicSemantics : latin:/?TypedDynamicLogic  ?State =
  include ?PropDynamicLogicSemantics
  include ?SFOLSemantics
  var = [S] tm cell S
  retrieve = [S,n] [w] n*w
  assign = [S,n,x] [v,w] extends v w n x 
  random_assign = [S,n] [v,w] ∃[t: tm W→S] extends v w n ([u]t@u)

namespace latin:/

fixmeta ur:?LF

theory UniversalQuantification =
  include ?UntypedLogic
  forall : (term ⟶ prop) ⟶ prop#  1##  V1 2


theory UniversalQuantificationNDI =
  include ?UniversalQuantification
  forallI  : {P} ({x} ⊦ (P x)) ⟶ ⊦ ∀ P


theory UniversalQuantificationNDE =
  include ?UniversalQuantification
  forallE  : {P,X} ⊦ ∀ P ⟶ ⊦ (P X)# 3 forallE 2role ForwardRule


theory UniversalQuantificationND =
  include ?UniversalQuantificationNDE 
  include ?UniversalQuantificationNDI 


theory ExistentialQuantification =
  include ?UntypedLogic
  exists : (term ⟶ prop) ⟶ prop#  1##  V1 2


theory ExistentialQuantificationNDI =
  include ?ExistentialQuantification
  existsI  : {P,X} ⊦ P X ⟶ ⊦ ∃ P# existsI 2 3


theory ExistentialQuantificationNDE =
  include ?ExistentialQuantification
  existsE  : {P,C} ⊦ ∃ P ⟶ ({x} ⊦ (P x) ⟶ ⊦ C) ⟶ ⊦ C# 3 existsE 4role EliminationRule


theory ExistentialQuantificationND =
  include ?ExistentialQuantificationNDI 
  include ?ExistentialQuantificationNDE 


theory IFOL =
  include ?IPL
  include ?UniversalQuantification
  include ?ExistentialQuantification


theory IFOLND =
  include ?IFOL
  include ?IPLND
  include ?UniversalQuantificationND
  include ?ExistentialQuantificationND


theory IFOLEQ =
  include ?IPL
  include ?Equality
  include ?UniversalQuantification
  include ?ExistentialQuantification


theory IFOLEQND =
  include ?IFOLEQ
  include ?IPLND
  include ?EqualityND
  include ?UniversalQuantificationND
  include ?ExistentialQuantificationND


theory FOL =
  include ?PL 
  include ?IFOL


theory FOLND =
  include ?FOL
  include ?PLND
  include ?IFOLND


theory FOLEQ =
  include ?FOL
  include ?Equality


theory FOLEQND =
  include ?FOLEQ
  include ?FOLND
  include ?EqualityND


theory RelativizedUniversalQuantification =
  include ?SoftTypedTerms
  include ?FOLEQ
  rforall : tp ⟶ (term ⟶ prop) ⟶ prop= [A,P] ∀[x] x⦂A ⇒ P x# ∀' 1 2


theory RelativizedUniversalQuantificationND =
  include ?RelativizedUniversalQuantification
  include ?FOLEQND
  rforallI : {A,F} ({x} ⊦x⦂A ⟶ ⊦ F x) ⟶ ⊦ ∀' A F= [A,F,P] forallI [x] impI [xa] P x xa
  rforallE : {A,F} ⊦ ∀' A F ⟶ {x} ⊦x⦂A ⟶ ⊦ F x= [A,F,p,x,xa] p forallE x impE xa


theory RelativizedExistentialQuantification =
  include ?SoftTypedTerms
  include ?FOLEQ
  rexists : tp ⟶ (term ⟶ prop) ⟶ prop= [A,P] ∃[x] x⦂A ∧ P x# ∃' 1 2


theory RelativizedExistentialQuantificationND =
  include ?RelativizedExistentialQuantification
  include ?FOLEQND
  rexistsI : {A,F} {x} ⊦x⦂A ⟶ ⊦ F x ⟶ ⊦ ∃' A F= [A,F,x,xa,p] existsI x andI xa p
  rexistsE : {A,F,C} ⊦ ∃' A F ⟶ ({x} ⊦x⦂A ⟶ ⊦ F x ⟶ ⊦ C) ⟶ ⊦ C= [A,F,C,p,P] p existsE [x,q] P x (q andEl) (q andEr)


theory UniqueExistentialQuantification =
  include ?ExistentialQuantification
  include ?Equality
  existsUnique  : (term ⟶ prop) ⟶ prop# ∃¹ 1  
 

theory UniqueExistentialQuantificationND =
  include ?UniqueExistentialQuantification 
  existsUniqueI : {P} {x} ⊦ P x ⟶ ({y} ⊦ P y ⟶ ⊦ x ≐ y) ⟶ ⊦ ∃¹ P# existsUniqueI 3 4 5
  existsUniqueE : {P,C} ⊦ ∃¹ P ⟶ ({x} ⊦ P x ⟶ ({y} ⊦ P y ⟶ ⊦ x ≐ y) ⟶ ⊦ C) ⟶ ⊦ C# 4 existsUniqueE 5


theory Description =
  include ?Logic
  include ?UniqueExistentialQuantification
  the : {P} ⊦ ∃¹ P ⟶ term# the 1 2
  the_ax : {P,p} ⊦ P (the P p)


theory Choice =
  include ?Logic
  include ?ExistentialQuantification
  some : {P} ⊦ ∃ P ⟶ term# some 1 2
  some_ax : {P,p} ⊦ P (some P p)


theory FOLEQDesc = 
  include ?FOLEQ
  include ?Description


theory FOLEQDescND =
  include ?FOLEQDesc
  include ?FOLEQND

namespace latin:/

theory UniversalQuantificationHilbert = 
  include ?UniversalQuantificationNDE
  include ?ImplicationHilbert 
  UQ_ax : {P} ⊦ ∀ [x] P x ⇒ ∀ P


// The following views need to be built ❚
// view HilbertNDEquivalence : ?EquivalenceHilbert → ?EquivalenceNDI =
  UQ_ax = ❙


// view NDHilbertEquivalence : ?EquivalenceNDI → ?EquivalenceHilbert =

namespace latin:/

fixmeta ur:?LF

theory InternalEquality =
  include ?InternalLogic
  include ?TypedEquality
  include ?SimpleFunctions
  equalConstant : {A} tm A → (A → bool)= [A]λ[x]λ[y]x≐y


theory PropositionalExtensionality =
  include ?InternalEquality
  propext: {F,G} (⊦ F ⟶ ⊦ G) ⟶ (⊦ G ⟶ ⊦ F) ⟶ ⊦ F≐G


theory IHOL =
  include ?InternalEquality
  include ?ISFOL
 

theory IHOLND =
  include ?InternalEquality
  include ?TypedEqualityND
  include ?ISFOLND
  include ?PropositionalExtensionality  
 

theory HOL =
  include ?IHOL


theory HOLND =
  include ?HOL
  include ?IHOLND
  include ?SFOLND
  include ?SimpleFunctionsEta
  
  eq_equiv: {F,G} ⊦F≐G ⟶ ⊦F⇔G= [F,G,p] equivI ([q] p congP ([u]u) q) ([q] (p sym) congP ([u]u) q)
  equiv_eq: {F,G} ⊦F⇔G ⟶ ⊦F≐G= [F,G,p] propext ([q] p equivEl q) ([q] p equivEr q)


theory PowerHOLND =
  include ?HOLND
  realize powertypes?PowerTypes

  power = [a] a → bool
  filter = [A,P] λ P
  in = [A,x,S] S @ x
  compute = [A,P,x] eq_equiv simpbeta
  expand = [A,S] eta sym

namespace latin:/

fixmeta ur:?LF

theory HOLAndrews =
  include ?InternalEquality
  include ?TypedEqualityND
  include ?PropositionalExtensionality
  
  // Remaining implementation is missing

  realize ?IHOLND❙
  // true = (λ[x:tm bool]x) ≐ λ[x]x❙
  // false = (λ[x]x) ≐ λ[x]true❙
  // not = [F]F ≐ false❙
  // forall = [A,P] (λ[x]P x) ≐ λ[x]true❙
  // and = [F,G] ∀[h:tm bool→bool→bool] h@F@G ≐ h@true@true❙
  // impl = [F,G] (F∧G) ≐ F❙
  // or = [F,G] ∀[H] (F⇒H) ⇒ (G⇒H) ⇒ H❙
  // equiv = [F,G] (F⇒G) ∧ (G⇒F)❙
  // exists = [A,F] ∀[H] (∀[x]F x ⇒ H) ⇒ H❙

namespace latin:/

fixmeta ur:?PLF

theory MetaLevelUniversalQuantification =
  include ?Logic
  forall : {A:type} (A ⟶ prop) ⟶ prop#  2 prec 30


theory MetaLevelExistentialQuantification =
  include ?Logic
  exists : {A:type} (A ⟶ prop) ⟶ prop#  2 prec 30


theory MetaLevelEquality =
  include ☞latin:/?Logic
  equal : {A:type} A ⟶ A ⟶ prop# 2  3 prec 30
  refl  : {A,x:A} ⊦ x ⊜ x# refl %I1 %I2
  transport : {A,x,y} ⊦ x ⊜ y ⟶ {T: A⟶type} T x ⟶ T y# transport 4 5 6
  cong  : {A,B,x,y} ⊦ x ⊜ y ⟶ {F: A⟶B} ⊦ F x ⊜ F y# 5 cong 6
        = [A,B,x,y,p,F] transport p ([a]  F x  F a) refl


theory MetaLogic =
  include ?MetaLevelEquality
  realize ?IPL
  realize ?MetaLevelUniversalQuantification
  realize ?MetaLevelExistentialQuantification
  true = ([x:prop]x) ⊜ [x]x
  false = ([x]x) ⊜ [x]true
  not = [F]F ⊜ false
  forall = [A,F] F ⊜ [x:A]true
  and = [F,G] ∀[h: prop ⟶ prop ⟶ prop]h F G ⊜ h true true
  impl = [F,G] (F∧G) ⊜ F
  or = [F,G] ∀[H] (F⇒H) ⇒ (G⇒H) ⇒ H
  equiv = [F,G] (F⇒G) ∧ (G⇒F)
  exists = [A,F] ∀[H] (∀[x]F x ⇒ H) ⇒ H

namespace latin:/

fixmeta ur:?LF

theory Box =
  include ?Logic
  box: prop ⟶ prop#  1 prec 20


theory Diamond =
  include ?Logic
  diamond: prop ⟶ prop#  1 prec 20


theory ML =
  include ?PL
  include ?Box
  include ?Diamond


theory MLHilbert =
  include ?ML
  // Rules with hypothetical premises are not sound in Kripke models; so we need to use a Hilbert calculus.❙
  include ?PLHilbert


namespace kripkemodels

theory Worlds : latin:/?HOLND =
  world: tp# W

  liftPred2: {S,A,B} (          tm A ⟶           tm B  ⟶          prop)
                   ⟶ (tm S ⟶ tm A) ⟶ (tm S ⟶ tm B) ⟶ (tm S ⟶ prop)
      = [S,A,B,o,f,g] [x] o (f x) (g x)
      # liftFun2 4

  lift0: {S} prop ⟶ (tm S ⟶ prop)
      = [S,o] [x]o
      # lift0 2
  lift1: {S} (prop ⟶ prop) ⟶ (tm S ⟶ prop) ⟶ (tm S ⟶ prop)
      = [S,o,f] [x]o (f x)
      # lift1 2
  lift2: {S} (prop ⟶ prop ⟶ prop) ⟶ (tm S ⟶ prop) ⟶ (tm S ⟶ prop) ⟶ (tm S ⟶ prop)
      = [S,o,f,g] [x]o (f x) (g x)
      # lift2 2
      
  liftbind : {S} ({T}  (        tm T            ⟶ prop)  ⟶          prop) ⟶
                  {T} ((tm S ⟶ tm T) ⟶ (tm S ⟶ prop)) ⟶ (tm S ⟶ prop)
           = [S][B][T][F][x] B (S→T) [f] F (apply1 f) x
           # liftbind 2
  


ref latin:/?DisjunctionHilbert2ND
ref latin:/?NegationHilbert2ND
ref latin:/?ImplicationHilbert2ND
ref latin:/?EquivalenceHilbert2ND

theory KripkeFrame : latin:/?TypedLogic =
  include ?Worlds
  accessible : tm W ⟶ tm W ⟶ prop # 1 acc 2 prec 30


theory KripkeModel =
  include ☞latin:/?SFOLEQ
  include ?KripkeFrame


view PropSemantics : latin:/?Propositions  ?Worlds =
  prop = tm W ⟶ prop


view LogicSemantics : latin:/?Logic  ?Worlds =
  include ?PropSemantics
  ded = [f] {w} ⊦ f w


view PLSemantics : latin:/?PL  ?Worlds =
  include ?PropSemantics
  true = lift0 true
  false = lift0 false
  and = lift2 and
  or = lift2 or
  impl = lift2 impl
  not = lift1 not
  equiv = lift2 equiv


view PLHilbertSemantics : latin:/?PLHilbert  ?Worlds =
  include ?PLSemantics
  include ?LogicSemantics
  
  trueI = [w] trueI
  falseE = [f] [g,w] f w falseE inconE
  
  andI  = [F,G,f,g][w] andI (f w) (g w)
  andEl = [F,G,fg] [w] fg w andEl
  andEr = [F,G,fg] [w] fg w andEr

  orIl = [F,G,f] [w] f w orIl
  orIr = [F,G,f] [w] f w orIr
  orE_ax = [F,G,H][w] orE_ax
  
  impE = [F,G,fg,f] [w] (fg w) impE (f w)
  K_ax = [F,G,w] K_ax
  S_ax = [F,G,H,w] S_ax
  
  notI_ax = [F,w] notI_ax 
  notE = [F,nf,f] [g,w] (nf w) notE (f w) inconE
  
  equivI_ax = [F,G,w] equivI_ax
  equivEl = [F,G,fg,f] [w] (fg w) equivEl (f w)
  equivEr = [F,G,fg,g] [w] (fg w) equivEr (g w)
  
  classical = [F,p] [w] classical [Fwincon] [A] p ([Fw,Gv,v] Fwincon (Fw w) (Gv v)) ([u] A) w


view TermSemantics : latin:/?TypedTerms  ?Worlds =
  /T constant universe; alternative would be tp = tm W ⟶ tp❙
  tp = tp
  tm = [S] tm W ⟶ tm S


view SFOLSemantics : latin:/?SFOLEQ  ?Worlds =
  include ?TermSemantics
  include ?PLSemantics
  include ?LogicSemantics
  forall = liftbind forall
  exists = liftbind exists
  equal = [S] liftFun2 (equal S)


view MLSemantics : latin:/?ML  ?KripkeModel =
  include ?PLSemantics
  include ?LogicSemantics
  box = [p] [v] ∀ [w] v acc w ⇒ p w
  diamond = [p] [v] ∃ [w] v acc w ∧ p w 


view MLHilbertSemantics : latin:/?MLHilbert  ?KripkeModel =
  include ?MLSemantics
  include ?PLHilbertSemantics

namespace latin:/

fixmeta ur:?LF

theory MultiModal =
  include ?Logic
  modality: type


theory MultiBox =
  include ?MultiModal
  box: modality ⟶ prop ⟶ prop#  1   2


theory MultiDiamond =
  include ?MultiModal
  diamond: modality ⟶ prop ⟶ prop#  1  2


theory MML =
  include ?MultiModal
  include ?MultiBox
  include ?MultiDiamond


theory SMML = 
  include ?MML
  include ?SFOLEQ


namespace kripkemodels

view MMLSemantics : latin:/?MML  ?Worlds =
  include ?LogicSemantics
  modality = tm W ⟶ tm W ⟶ prop
  box = [m,p] [v] ∀ [w] m v w ⇒ p w
  diamond = [m,p] [v] ∃ [w] m v w ∧ p w


view SMMLSemantics : latin:/?SMML  ?Worlds =
  include ?MMLSemantics
  include ?SFOLSemantics

namespace latin:/
import diagops scala://diagops.latin2

/T Declare operator constants

   Use an empty meta theory! E.g. if we used LF as a meta theory the notation
   would be parsed as LF-y.

theory LogicDiagramOperatorsSyntax =
  fol_typifier # TYPIFY FOL 1 prec -2000000 


theory LogicDiagramOperatorsSemantics : ur:?LF =
  include ☞http://cds.omdoc.org/urtheories?ModExp 
  rule diagops?ComputeFOLTypified 


theory LogicDiagramOperators =
  include ?LogicDiagramOperatorsSyntax 
  include ?LogicDiagramOperatorsSemantics 

  include ☞http://cds.omdoc.org/urtheories?Combinators 

namespace latin:/

fixmeta ur:?LF

theory PLModel =
  include ?SFOLEQND
  include ?Booleans


// View currently not total

view PLSemantics : ?PLND → ?PLModel =
  prop = tm bool❙
  ded  = [F] ⊦ F ≐ tt❙
  
  true = tt❙
  false = ff❙
  
  and   = [x,y] if x then y else ff❙
  or    = [x,y] if x then tt else y❙
  impl  = [x,y] if x then y else tt❙
  not   = [x] if x then ff else tt❙
  equiv = [x,y] if x then y else if y then ff else tt❙

  trueI = refl❙
  falseE = [p][a] (bool_nontrivial notE (p sym)) inconE❙
  
  andI = [F][G][p][q]
          trans3 (p congT [u] if u then G else ff) if_tt q❙


namespace latin:/

fixmeta ur:?LF

theory Tableaux =
  include ?Propositions 
  marktrue : prop ⟶ type  # 1 ¹ prec -5  role TabMarker 
  markfalse : prop ⟶ type  # 1  prec -5  role TabMarker 
  closedbranch : type  #   = {p} p¹   role TabClosed 

  // We could define many of the rules below by defining P⁰ = P¹ ⟶ ⊥ ❙

  closebranch : {P} P¹ ⟶ P⁰ ⟶ ⊥  # close10 2 3 
  closebranch2 : {P} P⁰ ⟶ P¹ ⟶ ⊥  # close01 2 3  = [P,p0,p1] close10 p1 p0 

  proofstart : {P} (P⁰ ⟶ ⊥) ⟶ P¹  # start1 2 
  refutationstart : {P} (P¹ ⟶ ⊥) ⟶ P⁰  # start0 2 

  classicality : {P} ((P¹ ⟶ ⊥) ⟶ ⊥) ⟶ P¹ 


// We need classicality to prove proofstart ❚
view Tableaux2Proofs : ?Tableaux -> ?Classical =
  prop = prop 
  marktrue = [p] ⊦ p 
  markfalse = [p] ⊦ p ⟶ ↯ 
  closedbranch = 
  closebranch = [P, p1, p0] p0 p1 
  proofstart = classical 
  classicality = classical 
  refutationstart = [P,pr] pr 


view Proofs2Tableaux : ?Proofs -> ?Tableaux =
  prop = prop 
  ded = [p] p¹ 
  // classical = classicality ❙



theory NegationTab =
  include ?Negation 
  include ?Tableaux 
  negationTab0 : {P} ¬P⁰ ⟶ (P¹ ⟶ ⊥) ⟶ ⊥  # negt0 2 3 
  negationTab1 : {P} ¬P¹ ⟶ (P⁰ ⟶ ⊥) ⟶ ⊥  # negt1 2 3 


view NegationTab2ND : ?NegationTab -> ?PLND =
  include ?Tableaux2Proofs 
  not = not 
  negationTab0 = [P, np0, p1r] np0 (notI p1r) 
  negationTab1 = [P, np1, p0r] np1 notE (classical p0r) 


view NegationND2Tab : ?NegationND -> ?NegationTab =
  include ?Proofs2Tableaux 
  not = not 
  notI = [F, fr : F¹ ⟶ ⊥] start1 ([nfr : ¬F⁰] negt0 nfr fr) 
  notE = [F, nf, f] negt1 nf ([f0] close10 f f0) 



theory ConjunctionTab =
  include ?Conjunction 
  include ?Tableaux 
  conjunctionTab0 : {A,B} A∧B⁰ ⟶ (A⁰ ⟶ ⊥) ⟶ (B⁰ ⟶ ⊥) ⟶ ⊥  # conjt0 3 4 5 
  conjunctionTab1 : {A,B} A∧B¹ ⟶ (A¹ ⟶ B¹ ⟶ ⊥) ⟶ ⊥  # conjt1 3 4 


// view ConjunctionTab2ND : ?ConjunctionTab -> ?PLND =
  and = and ❙



theory DisjunctionTab =
  include ?Disjunction 
  include ?Tableaux 
  disjunctionTab0 : {A,B} A∨B⁰ ⟶ (A⁰ ⟶ B⁰ ⟶ ⊥) ⟶ ⊥  # disjt0 3 4 
  disjunctionTab1 : {A,B} A∨B¹ ⟶ (A¹ ⟶ ⊥) ⟶ (B¹ ⟶ ⊥) ⟶ ⊥  # disjt1 3 4 5 



theory ImplicationTab =
  include ?Implication 
  include ?Tableaux 
  implicationTab0 : {A,B} A⇒B⁰ ⟶ (A¹ ⟶ B⁰ ⟶ ⊥) ⟶ ⊥  # implt0 3 4 
  implicationTab1 : {A,B} A⇒B¹ ⟶ (A⁰ ⟶ ⊥) ⟶ (B¹ ⟶ ⊥) ⟶ ⊥  # implt1 3 4 5 



theory EquivalenceTab =
  include ?Equivalence 
  include ?Tableaux 
  equivalenceTab0 : {A,B} A⇔B⁰ ⟶ (A⁰ ⟶ B¹ ⟶ ⊥) ⟶ (A¹ ⟶ B⁰ ⟶ ⊥) ⟶ ⊥  # equivt0 3 4 5 
  equivalenceTab1 : {A,B} A⇔B¹ ⟶ (A⁰ ⟶ B⁰ ⟶ ⊥) ⟶ (A¹ ⟶ B¹ ⟶ ⊥) ⟶ ⊥  # equivt1 3 4 5 


theory UniversalQuantificationTab =
  include ?UniversalQuantification 
  include ?Tableaux 
  forallT : {P, X} ∀ P ¹ ⟶ (P X ¹ ⟶ ⊥) ⟶ ⊥  role ApplyRepeatedly 
  forallF : {P} ∀ P ⁰ ⟶ ({x} P x ⁰ ⟶ ⊥) ⟶ ⊥ 


theory ExistentialQuantificationTab =
  include ?ExistentialQuantification 
  include ?Tableaux 
  existsT : {P} ∃ P ¹ ⟶ ({x} P x ¹ ⟶ ⊥) ⟶ ⊥ 
  existsF : {P, X} ∃ P ⁰ ⟶ (P X ⁰ ⟶ ⊥) ⟶ ⊥  role ApplyRepeatedly 

namespace latin:/

/T   Interdefinability of logics is formalized in various views. ❚

import rules scala://lf.mmt.kwarc.info
fixmeta ur:?LF

/T   The views currently still need single theories as a domain and codomain, which 
  forces us to provide spurious named theories. This should be refactored when
  multi-theory domains and codomains are possible. ❚
  
theory NegationTruth =
  include ?Negation
  include ?Truth


theory NegationFalsity =
  include ?Negation
  include ?Falsity


theory NegationTruthND =
  include ?NegationTruth
  include ?NegationNDE
  include ?TruthND


theory NegationFalsityND =
  include ?NegationFalsity
  include ?NegationND
  include ?FalsityND


view FalsityNegTruth : ?Falsity  ?NegationTruth =
  include ?Propositions 
  false = ¬ true 


view FalsityNegTruthND : ?FalsityND  ?NegationTruthND =
  include ?FalsityNegTruth
  include ?Proofs
  falseE = [p] p notE trueI 


view TruthNegFalsity : ?Truth  ?NegationFalsity =
  include ?Propositions 
  true = ¬ false 


view TruthNegFalsityND : ?TruthND  ?NegationFalsityND =
  include ?Propositions  
  include ?Proofs
  include ?TruthNegFalsity
  trueI = notI [p] p falseE


theory NegationConjunction =
  include ?Negation
  include ?Conjunction


view DisjNegConj : ?Disjunction  ?NegationConjunction =
  include ?Propositions 
  or = [a,b] ¬(¬a ∧ ¬b)


theory NegationDisjunction =
  include ?Negation
  include ?Disjunction


view ConjNegDisj : ?Conjunction  ?NegationDisjunction =
  include ?Propositions 
  and = [a,b] ¬(¬a ∨ ¬b)


theory NegationImplication =
  include ?Negation
  include ?Implication


view DisjNegConj : ?Disjunction  ?NegationImplication =
  include ?Propositions 
  or = [a,b] ¬a ⇒ b


theory NegationDisjunction =
  include ?Negation
  include ?Disjunction


view ImplNegDisj : ?Implication  ?NegationDisjunction =
  include ?Propositions 
  impl = [a,b] ¬a ∨ b


theory NegationConjunction =
  include ?Negation
  include ?Conjunction


view ImplNegConj : ?Implication  ?NegationConjunction =
  include ?Propositions 
  impl = [a,b] ¬(a ∧ ¬b)


theory ImplicationConjunction =
  include ?Implication
  include ?Conjunction


view EquivImplConj : ?Equivalence  ?ImplicationConjunction =
  include ?Propositions 
  equiv = [a,b] (a ⇒ b) ∧ (b ⇒ a)


theory ImplicationFalsity =
  include ?Implication
  include ?Falsity


view NegImplFalsity : ?Negation  ?ImplicationFalsity =
  include ?Propositions 
  not = [a] a ⇒ false

namespace latin:/

/T A fully modular specification of intuitionistic and classical propositional
  logics.
  Every connective and all proof rules are specified in their own theories to maximize reusability.
  
  Proof rules follow natural deduction except that a judgment for inconsistency is used in some rules.


/T Naming conventions for theory name suffixes
   * ND: natural deduction rules
   * I resp. E: introduction resp. elimination rules


import rules scala://lf.mmt.kwarc.info
fixmeta ur:?LF

theory Truth =
  include ?Propositions
  true  : prop


theory TruthND =
  include ?Truth
  include ?Proofs
  trueI : ⊦ true


theory Falsity =
  include ?Propositions
  false  : prop


theory FalsityND =
  include ?Falsity
  include ?Proofs
  falseE : ⊦ false ⟶ ↯# 1 falseE


theory Negation =
  include ?Propositions
  not   : prop ⟶ prop# ¬ 1   prec 20


theory NegationNDI =
  include ?Negation
  include ?Proofs
  notI  : {F} (⊦ F ⟶ ↯) ⟶ ⊦ ¬ F# notI 2


theory NegationNDE =
  include ?Negation
  include ?Proofs
  notE  : {F} ⊦ ¬ F ⟶ ⊦ F ⟶ ↯# 2 notE 3


theory NegationND =
  include ?NegationNDI
  include ?NegationNDE


theory AlternativeNegationAndFalsityND =
  include ?Proofs 
  include ?Falsity 
  include ?Negation 
  include ?Disjunction 
  notIntroduction : {A} (⊦ A ⟶ ⊦ false) ⟶ (⊦ ¬ A)  # altNotI 2 
  notElimination : {A} ⊦ ¬ ¬ A ⟶ ⊦ A  # altNotE 2 
  falseIntroduction : {A} ⊦ ¬ A ⟶ ⊦ A ⟶ ⊦ false  # altFI 2 3  role EliminationRule 
  falseElimination : {A} ⊦ false ⟶ ⊦ A  # altFE 1 2 


theory Conjunction =
  include ?Propositions
  and   : prop ⟶ prop ⟶ prop# 1  2 prec 15


theory ConjunctionNDI =
  include ?Conjunction
  include ?Proofs
  andI  : {F,G} ⊦ F ⟶ ⊦ G ⟶ ⊦ F ∧ G


theory ConjunctionNDE =
  include ?Conjunction
  include ?Proofs
  andEl : {F,G} ⊦ F ∧ G ⟶ ⊦ F# 3 andElrole ForwardRule
  andEr : {F,G} ⊦ F ∧ G ⟶ ⊦ G# 3 andErrole ForwardRule


theory ConjunctionND =
  include ?ConjunctionNDI
  include ?ConjunctionNDE


theory Disjunction =
  include ?Propositions
  or    : prop ⟶ prop ⟶ prop# 1  2 prec 15


theory DisjunctionNDI =
  include ?Disjunction
  include ?Proofs
  orIl  : {F,G} ⊦ F ⟶ ⊦ F ∨ G# 3 orIl
  orIr  : {F,G} ⊦ G ⟶ ⊦ F ∨ G# 3 orIr


theory DisjunctionNDE =
  include ?Disjunction
  include ?Proofs
  orE   : {F,G,C} ⊦ F ∨ G ⟶ (⊦ F ⟶ ⊦ C) ⟶ (⊦ G ⟶ ⊦ C) ⟶ ⊦ C# 4 orE 5 6role EliminationRule


theory DisjunctionND =
  include ?DisjunctionNDI
  include ?DisjunctionNDE


theory Implication =
  include ?Propositions
  impl  : prop ⟶ prop ⟶ prop# 1 %R⇒ 2 prec 10  


theory ImplicationNDI =
  include ?Implication
  include ?Proofs
  impI  : {F,G} (⊦ F ⟶ ⊦ G) ⟶ ⊦ F ⇒ G


theory ImplicationNDE =
  include ?Implication
  include ?Proofs
  impE  : {F,G} ⊦ F ⇒ G ⟶ ⊦ F ⟶ ⊦ G# 3 impE 4role ForwardRule


theory ImplicationND =
  include ?ImplicationNDI
  include ?ImplicationNDE
  
  total structure impl_preorder : ?Preorder =
    carrier = prop
    rel = [x,y] ⊦ x ⇒ y
    refl = [F] impI [f] f
    trans = [F,G,H,fg,gh] impI [f] gh impE (fg impE f) 
  


theory Equivalence =
  include ?Propositions
  equiv : prop ⟶ prop ⟶ prop# 1  2 prec 10
 

theory EquivalenceNDI =
  include ?Equivalence
  include ?Proofs
  equivI : {F,G} (⊦ F ⟶ ⊦ G) ⟶ (⊦ G ⟶ ⊦ F) ⟶ ⊦ F ⇔ G


theory EquivalenceNDE =
  include ?Equivalence
  include ?Proofs
  equivEl : {F,G} ⊦ F ⇔ G ⟶ ⊦ F ⟶ ⊦ G# 3 equivEl 4role ForwardRule
  equivEr : {F,G} ⊦ F ⇔ G ⟶ ⊦ G ⟶ ⊦ F# 3 equivEr 4role ForwardRule


theory EquivalenceND =
  include ?EquivalenceNDI
  include ?EquivalenceNDE
  
  total structure equiv_equivalence : ?EquivalenceRelation =
    carrier = prop
    rel = [x,y] ⊦ x ⇔ y
    refl = [F] equivI ([p]p) ([p]p)
    sym  = [F,G,p] equivI ([q] p equivEr q) ([q] p equivEl q)
    trans = [F,G,H,fg,gh] equivI ([f] gh equivEl (fg equivEl f))
                                 ([h] fg equivEr (gh equivEr h))
  


theory IPL =
  include ?Propositions
  include ?Truth
  include ?Falsity
  include ?Negation
  include ?Conjunction
  include ?Disjunction
  include ?Implication
  include ?Equivalence


theory IPLND =
  include ?IPL
  include ?Logic
  include ?TruthND
  include ?FalsityND
  include ?NegationND
  include ?ConjunctionND
  include ?DisjunctionND
  include ?ImplicationND
  include ?EquivalenceND
  
  not_or_left : {F,G} ⊦ ¬(F∨G) ⟶ ⊦¬F = [F,G,p] notI [q] p notE (q orIl)
  not_or_right : {F,G} ⊦ ¬(F∨G) ⟶ ⊦¬G = [F,G,p] notI [q] p notE (q orIr)
  nntnd : {F} ⊦¬¬(F∨¬F)= [F] notI [p] (not_or_right p) notE (not_or_left p)

  total structure impl_order : ?Order =
    include ?ImplicationND/impl_preorder 
    structure equalityRel = ?EquivalenceND/equiv_equivalence
    antisym = [F,G,fg,gf] equivI ([f] fg impE f) ([g] gf impE g)
  


theory Classical =
  include ?Logic
  classical : {F} ((⊦ F ⟶ ↯) ⟶ ↯) ⟶ ⊦ F# classical 2


theory ProofIrrelevance =
  include ?Logic
  rule rules?TermIrrelevanceRule ded


theory PL =
  include ?IPL


theory PLND =
  include ?PL
  include ?IPLND
  include ?ProofIrrelevance
  include ?Classical

  indirect : {F} (⊦¬F ⟶ ↯) ⟶ ⊦ F= [F,h] classical [q] h (notI q)# indirect 2  
  dne : {F} ⊦¬¬F ⟶ ⊦F= [F,p] indirect [q] p notE q
  tnd : {F} ⊦F∨¬F= [F] dne nntnd


/T Conjunction where the second conjunct's well-formedness may depend on the truth of the first conjunct
   Curry-Howard analogue of Sigma types ❚
theory DependentConjunction =
  include ?Logic
  dand   : {F} (⊦ F ⟶ prop) ⟶ prop# 1 ∧- 2 prec 10


theory DependentConjunctionND =
  include ?DependentConjunction
  dandI  : {F,G} {p:⊦ F} ⊦ G p ⟶ ⊦ F ∧- G
  dandEl : {F,G} ⊦ F ∧- G ⟶ ⊦ F# 3 dandElrole ForwardRule
  dandEr : {F,G} {p: ⊦ F ∧- G} ⊦ G (p dandEl)# 3 dandErrole ForwardRule


/T Disjunction where the second disjunct's well-formedness may depend on the falsity of the first disjunct
   Curry-Howard analogue of an unusual union type where the second argument is only considered if the first one is empty❚ 
theory DependentDisjunction =
  include ?Logic
  dor    : {F} ((⊦ F ⟶ ↯) ⟶ prop) ⟶ prop# 1 ∨- 2 prec 10


theory DependentDisjunctionND =
  include ?DependentDisjunction
  dorIl  : {F,G} ⊦ F ⟶ ⊦ F ∨- G# 3 dorIl
  dorIr  : {F,G} ({p:⊦ F ⟶ ↯} ⊦ G p) ⟶ ⊦ F ∨- G# 3 dorIr
  dorE   : {F,G,C} ⊦ F ∨- G ⟶ (⊦ F ⟶ ⊦ C) ⟶ ({p: ⊦ F ⟶ ↯} ⊦ G p ⟶ ⊦ C) ⟶ ⊦ C# 4 dorE 5 6


/T Implication where the implicate's well-formedness may depend on the truth of the implicant
   Curry-Howard analogue of Pi types ❚
theory DependentImplication =
  include ?Logic
  dimpl  : {F} (⊦ F ⟶ prop) ⟶ prop# 1 ⇒- 2 prec 10


theory DependentImplicationND =
  include ?DependentImplication
  dimpI  : {F,G} ({p} ⊦ G p) ⟶ ⊦ F ⇒- G
  dimpE  : {F,G} ⊦ F ⇒- G ⟶ {p:⊦ F} ⊦ G p# 3 dimpE 4role ForwardRule

namespace latin:/

/T Hilbert calculi for propositional and first-order logic. 
  Here we formalize a version that is rule-maximal, i.e. we include 
  as many rules from natural deduction a we can, i.e. all rules that 
  do not use hypothetical reasoning. The ones that do, we reformulate 
  into axioms, where all the function types become implications. 
  
  Unfortunately, this means that we cannot be fully modular, since we 
  need a treatment of implication in all cases.❚

theory ImplicationHilbert = 
  include ?ImplicationNDE
  K_ax : {F,G} ⊦ F ⇒ G ⇒ F 
  S_ax : {F,G,H} ⊦ (F ⇒ G ⇒ H) ⇒ (F ⇒ G) ⇒ F ⇒ H 


theory NegationHilbert = 
  include ?NegationNDE
  include ?ImplicationHilbert
  notI_ax : {F} ⊦ (F ⇒ ¬F) ⇒ ¬F 


theory DisjunctionHilbert = 
  include ?DisjunctionNDI
  include ?ImplicationHilbert 
  orE_ax : {F,G,H} ⊦ (F ∨ G) ⇒ (F ⇒ H) ⇒ (G ⇒ H) ⇒ H


theory EquivalenceHilbert = 
  include ?EquivalenceNDE
  include ?ImplicationHilbert 
  equivI_ax : {F,G} ⊦ (F ⇒ G) ⇒ (G ⇒ F) ⇒ (F ⇔ G)


theory PLHilbert =
  include ?PL
  include ?ImplicationHilbert
  include ?TruthND
  include ?FalsityND
  include ?ConjunctionND
  include ?NegationHilbert
  include ?DisjunctionHilbert
  include ?EquivalenceHilbert
  include ?Classical


implicit view ImplicationHilbert2ND : ?ImplicationHilbert  ?ImplicationND =
  include ?ImplicationNDE
  K_ax = [F,G] impI [p] impI [q] p 
  S_ax = [F,G,H] impI [p] impI [q] impI [r] (p impE r) impE (q impE r)


implicit view NegationHilbert2ND : ?NegationHilbert  ?PLND =
  include ?NegationNDE
  include ?ImplicationHilbert2ND
  notI_ax = [F] impI [p] notI [q] (p impE q) notE q


implicit view DisjunctionHilbert2ND : ?DisjunctionHilbert  ?PLND =
  include ?DisjunctionNDI
  include ?ImplicationHilbert2ND
  orE_ax = [F,G,H] impI [fg] impI [fh] impI [gh] fg orE ([f] fh impE f) ([g] gh impE g)


implicit view EquivalenceHilbert2ND : ?EquivalenceHilbert  ?PLND =
  include ?EquivalenceNDE
  include ?ImplicationHilbert2ND
  equivI_ax = [F,G] impI [fg] impI [gf] equivI ([f] fg impE f) ([g] gf impE g)


implicit view PLHilbert2ND : ?PLHilbert  ?PLND =
  include ?PL
  include ?ImplicationHilbert2ND
  include ?TruthND
  include ?FalsityND
  include ?ConjunctionND
  include ?NegationHilbert2ND
  include ?DisjunctionHilbert2ND
  include ?EquivalenceHilbert2ND
  include ?Classical

namespace latin:/

fixmeta ur:?LF

diagram SFOL_via_operator : ?LogicDiagramOperators := TYPIFY FOL DIAG FROM FILE "C:\Users\nroux\Desktop\kwarc-project\code\archives\MathHub\MMT\LATIN2\source\logic\fol.mmt" 

theory TypedUniversalQuantification =
  include ?TypedLogic
  forall : {A} (tm A ⟶ prop) ⟶ prop#  2


theory TypedUniversalQuantificationND =
  include ?TypedUniversalQuantification
  forallI  : {A,P} ({x: tm A} ⊦ P x) ⟶ ⊦ ∀ [x] P x
  forallE  : {A,P} ⊦ ∀ P ⟶ {x: tm A} ⊦ P x# 3 forallE 4role ForwardRule


theory TypedExistentialQuantification =
  include ?TypedLogic
  exists : {A} (tm A ⟶ prop) ⟶ prop#  2


theory TypedExistentialQuantificationND =
  include ?TypedExistentialQuantification
  existsI  : {A,P} {x: tm A} ⊦ P x ⟶ ⊦ ∃ P# existsI 3 4
  existsE  : {A,P,C} ⊦ ∃ P ⟶ ({x: tm A} ⊦ P x ⟶ ⊦ C) ⟶ ⊦ C# 4 existsE 5


theory ISFOL =
  include ?TypedTerms
  include ?IPL
  include ?TypedUniversalQuantification
  include ?TypedExistentialQuantification


theory ISFOLND =
  include ?ISFOL
  include ?IPLND
  include ?TypedUniversalQuantificationND
  include ?TypedExistentialQuantificationND


theory SFOL =
  include ?PL
  include ?ISFOL


theory SFOLND =
  include ?SFOL
  include ?PLND
  include ?ISFOLND


theory SFOLEQ =
  include ?SFOL
  include ?TypedEquality
  notequal : {A} tm A ⟶ tm A ⟶ prop= [A,x,y]¬x≐y# 2  3 prec 30


theory SFOLEQND =
  include ?SFOLEQ
  include ?SFOLND
  include ?TypedEqualityND


theory TypedUniqueExistentialQuantification =
  include ?TypedExistentialQuantification
  include ?TypedEquality
  existsUnique  : {A} (tm A ⟶ prop) ⟶ prop# ∃¹ 2


theory TypedUniqueExistentialQuantificationND =
  include ?TypedUniqueExistentialQuantification
  existsUniqueI : {A,P} {x: tm A} ⊦ P x ⟶ ({y} ⊦ P y ⟶ ⊦ x ≐ y) ⟶ ⊦ ∃¹ P# existsUniqueI 3 4 5
  existsUniqueE : {A,P,C} ⊦ ∃¹ P ⟶ ({x: tm A} ⊦ P x ⟶ ({y} ⊦ P y ⟶ ⊦ x ≐ y) ⟶ ⊦ C) ⟶ ⊦ C# 4 existsUniqueE 5


theory TypedDescription =
  include ?TypedLogic
  include ?TypedUniqueExistentialQuantification
  the : {A} {P:tm A ⟶ prop} ⊦ ∃¹ P ⟶ tm A# the 2 3
  the_ax : {A,P: tm A ⟶ prop,p} ⊦ P (the P p)


theory TypedChoice =
  include ?TypedLogic
  include ?TypedExistentialQuantification
  some : {A} {P:tm A ⟶ prop} ⊦ ∃ P ⟶ tm A# some 2 3
  some_ax : {A,P: tm A ⟶ prop,p} ⊦ P (some P p)

namespace latin:/ 

import lfx http://gl.mathhub.info/MMT/LFX/TypedHierarchy 
import finite http://gl.mathhub.info/MMT/LFX/Finite 
import rules scala://structuralfeatures.lf.mmt.kwarc.info

// Mainly ported (with very minor modifications)
// from Colin's examples/induction/NatExample.mmt


theory NatInduct : ?LFXI =
  inductive nat() =
    n: type  
    z: n     
    s: n ⟶ n 
  

  inductive_definition plusn() : nat() =
    n: type  = (nat/n ⟶ nat/n)     
    z: n     = ([x] x)             
    s: n ⟶ n = ([u,x] nat/s (u x)) 
  

  plus: nat/n ⟶ nat/n ⟶ nat/n
    = plusn/n
    # 1 + 2
  

  z_plus_n: {m: nat/n} DED ((nat/z + m) EQ m) 
  z_plus_z: DED (nat/z + nat/z) EQ nat/z 
  z_plus_suc: {m: nat/n} DED (nat/z + m) EQ m ⟶ DED (nat/z + (nat/s m)) EQ (nat/s m) 

  ind_proof z_neutral() : nat() =
    n = [m] DED (nat/z + m) EQ m 
    z : n nat/z = plusn/z/Applied nat/z 
    s : {x:nat/n} n x ⟶ n (nat/s x) = [x, px] plusn/z/Applied (nat/s x) 
  

  inductive_definition times() : nat() =
    n: type  = (nat/n ⟶ nat/n)     
    z: n     = ([x] nat/z)         
    s: n ⟶ n = ([u,x] (x + (u x))) 
  

  inductive_definition predec() : nat() =
    n: type  = nat/n   
    z: n     = nat/z   
    s: n ⟶ n = ([u] u) 
  

  inductive_definition monus() : nat() =
    n: type  = (nat/n ⟶ nat/n)        
    z: n     = ([x] x)                
    s: n ⟶ n = ([u,x] predec/n (u x)) 
  

namespace latin:/

fixmeta latin:/?SFOLEQND

import rules scala://lf.mmt.kwarc.info
import uom scala://uom.api.mmt.kwarc.info

theory Nat =
  nat   : tp
  Nat = tm nat# 
  zero  : 
  succ  : ℕ ⟶ ℕ # 1 ' prec 20
  
  rule rules?Realize ℕ uom?StandardNat
  rule rules?Realize zero uom?Arithmetic/Zero
  rule rules?Realize succ uom?Arithmetic/Succ

namespace latin:/

import proving scala://latin2/proving

theory PropositionsITP =
  proof # block proof 1;
  rule proving?CheckProof

  hence  # %n L1T by 2
  suffices # %n 1 
  use # use 1
  rule proving?UseStep


theory PLITP =
  include ?PropositionsITP

  assume # %n L1T
  rule proving?AssumeStep
  cases # %n 1,


theory SFOLITP =
  include ?PLITP
  fix    # %n L1T
  rule proving?FixStep


theory Test : ?SFOLITP =
  include ?SFOLEQND

  test : {T,A: tm T⟶ prop} ⊦ ∀ [x] A x ⇒ A x
       = [T,A] proof fix x; assume a; use a
  
  // the above is equivalent to the following in standard natural deduction❙
  test2 : {T,A: tm T⟶ prop} ⊦ ∀ [x] A x ⇒ A x
       = [T,A] forallI [x] impI [a] a

namespace latin:/

theory SetFOL : ur:?LF =
  include ?FOLEQND
  set = term
  include ?InternalTypes
  include ?Description
  include ?RelativizedUniversalQuantificationND
  include ?RelativizedExistentialQuantificationND


fixmeta ?SetFOL

theory Empty =
  isempty : set ⟶ prop= [x] ¬ ∃[y] y ∈ x
  empty : set# 
  empty_prop : ⊦ isempty ∅
  emptyE : {x} ⊦ x∈∅ ⟶ ↯= [x,p] empty_prop notE (existsI x p)


theory UnorderedPairs =
  uopair : set ⟶ set ⟶ set
  uopairIL : {X,Xˈ} ⊦ X ∈ uopair X Xˈ
  uopairIR : {X,Xˈ} ⊦ X ∈ uopair X Xˈ
  uopairE  : {U,X,Xˈ} ⊦ U ∈ uopair X Xˈ ⟶ ⊦ U≐X ∨ U≐Xˈ


theory Singletons =
  singleton : set ⟶ set
  singletonI : {x} ⊦ x ∈ singleton x
  singletonE : {x,u} ⊦ u ∈ singleton x ⟶ ⊦ u≐x
  
  issingleton : set ⟶ prop= [x] ∃¹[u]u∈x
  singleton_the : {x} ⊦ issingleton x ⟶ set= [x,p] the ([u] u ∈ x) p


view SelfPair : ?Singletons  ?UnorderedPairs =
  singleton = [x] uopair x x
  singletonI = [x] uopairIL
  singletonE = [x,u,p] uopairE p orE ([q] q) ([q] q)


theory Comprehension =
  comprehend  : set ⟶ (set ⟶ prop) ⟶ set# 1 | 2 prec 40
  comprehendI : {A,P,X} ⊦ X∈A ⟶ ⊦ P X ⟶ ⊦ X ∈ A|P
  comprehend_sub : {A,P,X} ⊦ X ∈ A|P ⟶ ⊦ X∈A
  comprehendE : {A,P,X} ⊦ X ∈ A|P ⟶ ⊦ P X


theory Replacement =
  replace  : set ⟶ (set ⟶ set) ⟶ set# 1 map 2 prec 40
  replaceI : {A,F,X} ⊦ X∈A ⟶ ⊦ (F X) ∈ A map F
  replaceE : {A,F,X} ⊦ X ∈ A map F ⟶ ⊦ ∃'A [x] (F x) ≐ X


theory BigUnion =
  bigunion : set ⟶ set#  1
  bigunionI : {A,X,x} ⊦ x∈X ⟶ ⊦ X∈A ⟶ ⊦ x ∈ ⋃A
  bigunionE : {A,X,x,C} ⊦ x ∈ ⋃A ⟶ (⊦ X∈A ⟶ ⊦ x∈X ⟶ ⊦ C) ⟶ ⊦ C


theory PowerSets =
  power : set ⟶ set#  1 prec 60
  powerI : {X,A} ({u} ⊦u∈X ⟶ ⊦u∈A) ⟶ ⊦X∈℘ A
  powerE : {X,A} ⊦X∈℘A ⟶ {u} ⊦u∈X ⟶ ⊦u∈A


theory Infinite =

namespace latin:/

fixmeta latin:/powertypes?PowerSFOL

theory ClosureSystem =
  X  : tp
  CC : tm ℘℘X
  
  intersection : {Q: tm ℘℘X} ⊦ Q ⊆ CC ⟶ ⊦ (⋂ Q) ∈ CC
  // provable ❙
  full_closed  : ⊦ fullset ∈ CC


theory ClosureOperator =
  X       : tp
  closure : tm ℘X ⟶ tm ℘X # cl 1 prec 50
  
  extensive    : {A} ⊦ A ⊆ cl A
  monotone     : {A,B} ⊦ A ⊆ B ⟶ ⊦ cl A ⊆ cl B
  idempotent   : {A} ⊦ cl (cl A) ≐ cl A


theory InteriorTopology = 
	X : tp 
	interior : tm ℘X ⟶ tm ℘X

	int_extensivity : {A} ⊦ ( subset X (interior A) A)
	idempotence : {A} ⊦ ((interior A) ≐  (interior (interior A)))
	bin_inters : {A, B} ⊦ ((interior (A ∩ B)) ≐ ((interior A) ∩ (interior B)))
	preservation : ⊦ ((interior (full X)) ≐ (full X))
	


theory ClosureTopology =
  include ?ClosureOperator

  closure_empty  : ⊦ cl (empty X) ≐ (empty X)
  closure_union  : {A,B} ⊦ cl (A ∪ B) ≐ cl A ∪ cl B
  
  // monotone provable from union❙ 


//   isomorphic to ClosureOperator❚
theory Closeness =
  X     : tp
  close : tm X ⟶ tm ℘X ⟶ prop # 1 | 2 prec 40

  in_close     : {x,A} ⊦ x ∈ A ⟶ ⊦ x|A
  bigger_close : {x,A,B} ⊦ x|A ⟶ ⊦ A ⊆ B ⟶ ⊦ x|B
  transitive   : {A,B,x} ⊦ x|B ⟶ ⊦ (∀ [y] y ∈ B ⇒ y|A) ⟶ ⊦ x|A

  
theory ClosenessTopology =
  include ?Closeness

  empty_union  : {x} ⊦ ¬ x|(empty X)
  finite_union : {x,A,B} ⊦ x|(A ∪ B) ⟶ ⊦ x|A ∨ x|B
  
  // bigger_close provable from union ❙


//   empty and full axioms are implied by/correspond to empty union and empty intersection❚
theory OpenTopology =
  X     : tp
  OO    : tm ℘℘X
  
  full_open  : ⊦ (full X) ∈ OO
  union_open : {Q: tm ℘℘X} ⊦ Q ⊆ OO ⟶ ⊦ (⋃ Q) ∈ OO

  empty_open : ⊦ (empty X) ∈ OO 
  finite_intersection : {A,B} ⊦ A ∈ OO ⟶ ⊦ B ∈ OO ⟶ ⊦ A ∩ B ∈ OO


theory ClosedTopology =
  include ?ClosureSystem  
  empty_closed : ⊦ (empty X) ∈ CC
  finite_union : {A,B} ⊦ A ∈ CC ⟶ ⊦ B ∈ CC ⟶ ⊦ A ∪ B ∈ CC


theory NeighborhoodTopology =
  X     : tp
  NN    : tm X ⟶ tm ℘℘X
  neighborhood: tm X ⟶ tm ℘X ⟶ prop
              = [x,N] N ∈ (NN x)# 1  2 prec 30
  
  nonempty : {x} ⊦ ¬ (NN x) ≐ ∅
  inneighborhood : {x: tm X,N} ⊦ x ∘ N ⟶ ⊦ x ∈ N
  superset_closed   : {M,N,x} ⊦ x ∘ M ⟶ ⊦ M ⊆ N ⟶ ⊦ x ∘ N
  intersection_closed : {M,N,x} ⊦ x ∘ M ⟶ ⊦ x ∘ N ⟶ ⊦ x ∘ M ∩ N
  openness       : {N,x} ⊦ x ∘ N ⟶ ⊦ ∃[M]∀[y] x ∘ M ∧ (y∈M ⇒ y∘N)

namespace latin:/

// views
   ClosureSystem ⟶ ClosureOperator: A closed if A fixed point of cl
   ClosureOperator ⟶ ClosureSystem: cl A = intersection of closed supersets of A
   Closeness ↔ ClosureOperator: X close A ⇔ X ‍∈ cl A
   ClosureSystem ⟶ Closeness: A closed if A contains all points close to it 
   Closeness ↔ ClosureSystem: X close A if X in every closed superset of A

for functions f: X ⟶ Y
  f(cl A) ⊆‍ cl f(A)  ⇔  preservation of closeness   ⇔  reflection of closedness  (= continuous)
  f(cl A) ⊇ cl f(A)  ⇔  preservation of closedness


//   views:
      Neighborhood ⟶ Open: NN = supersets of open sets
      Open ⟶ Neighborhood: OO = sets that are neightborhoods for every element
      Open ⟶ Closed: OO = complements of CC
      Closed ⟶ Open: CC = complements of OO

namespace latin:/

fixmeta ?SFOLEQND

theory Option =
  option: tp ⟶ tp  # 1 ? prec 100  // unfortunately the notation ? does not work in binders, so use 'option A' there
  some: {A: tp} tm A ⟶ tm A?  # some 2
  none: {A: tp} tm A?  # none %I1 

  defined_and_equal_to: {A: tp} tm A? ⟶ tm A ⟶ prop
     = [A, optionValue, value] optionValue ≐ some value
     # 2  3 prec 20 

  defined: {A: tp} tm A? ⟶ prop
     = [A, optionValue] ∃[v: tm A] optionValue ≡ v
     # 2  prec 20  // we need higher precedence than ∧ (which is 10 currently) 

  if_defined_then_equal_to: {A: tp} tm A? ⟶ tm A ⟶ prop
     = [A, optionValue, value] optionValue ≐ none ∨ optionValue ≡ value
     # ifDefEq 2 3
    

  both_defined_and_equal: {A: tp} tm A? ⟶ tm A? ⟶ prop
     = [A, optionValue1, optionValue2] optionValue1↓ ∧ optionValue2↓ ∧ optionValue1 ≐ optionValue2
     # bothDefEq 2 3
   

  equality_ax: {A: tp} ⊦ ∀[optionValue1: tm (option A)] ∀[optionValue2: tm (option A)]
      optionValue1 ≐ optionValue2 ⇔ (optionValue1 ≐ none ∧ optionValue2 ≐ none) ∨ (∃[v: tm A] optionValue1 ≡ v ∧ optionValue2 ≡ v) 

  map: {A, B} tm A? ⟶ (tm A ⟶ tm B) ⟶ tm B?  # map 3 4 prec 25
  map_ax1: {A, B, f: tm A ⟶ tm B, a: tm A} ⊦ map (some a) f ≡ f a 
  map_ax2: {A, B, f: tm A ⟶ tm B} ⊦ (map none f) ≐ none 

  flatMap: {A, B} tm A? ⟶ (tm A ⟶ tm (option B)) ⟶ tm B?  # flatMap 3 4 prec 25 


theory ObjectLessComposition =
  include ?Option 
  mor: tp 
  Mor = tm mor 
  OptionMor = tm mor?  # Mor? 
  composition: Mor ⟶ Mor ⟶ Mor?  # 2  1 prec 200 

  // The question mark is on the optional side ❙
  opt_composition: Mor? ⟶ Mor ⟶ Mor?
     = [α, β] flatMap α ([z] z ∘ β)
     # 2 ∘? 1
  

  // The question mark is on the optional side ❙
  composition_opt: Mor ⟶ Mor? ⟶ Mor?
     = [α, β] flatMap β ([z] α ∘ z)
     # 2 ?∘ 1
  


// Object-less category theory according to
    https://arxiv.org/pdf/1602.01759.pdf ❚
theory ObjectLessCategory =
  include ?Option 
  include ?ObjectLessComposition 

  associativity: {α: Mor, β: Mor, γ: Mor}
    ⊦ (α ∘ β)↓ ∧ (β ∘ γ)↓ ⇒ (α ∘? (β ∘ γ))↓ ∧ ((α ∘ β) ?∘ γ)↓ ∧ (α ∘? (β ∘ γ)) ≐ ((α ∘ β) ?∘ γ)
  
  existence_of_subcompositions1: {α: Mor, β: Mor, γ: Mor} ⊦ (α ∘? (β ∘ γ))↓ ⇒ (α ∘ β)↓ 
  existence_of_subcompositions2: {α: Mor, β: Mor, γ: Mor} ⊦ ((α ∘ β) ?∘ γ)↓ ⇒ (β ∘ γ)↓ 

  leftIdentity: {m: Mor} Mor  # ' 1 prec 20 
  leftIdentityAlternativeNotation = leftIdentity  # dom 1 prec 20 
  rightIdentity: {m: Mor} Mor  # 1 '' prec 20  // notation ' 1 doesn't work with MMT's notation parser somehow 
  rightIdentityAlternativeNotation = rightIdentity  # cod 1 prec 20 

  ax_leftIdentityComposable: {α: Mor} ⊦ (α ∘ 'α)↓ 
  ax_rightIdentityComposable: {α: Mor} ⊦ (α'' ∘ α)↓ 

  ax_leftIdentityNeutral : {α: Mor, β: Mor} ⊦ (ifDefEq  (β ∘ 'α) β) ∧ (ifDefEq  (('α) ∘ β) β)
  ax_rightIdentityNeutral: {α: Mor, β: Mor} ⊦ (ifDefEq (β ∘ (α'')) β) ∧ (ifDefEq (α'' ∘ β) β)
  // {β: Mor} ⊦ (β ∘ ⟜β)↓ ⇒ (β ∘ ⟜β) ≡ β ❙

  is_identity: Mor ⟶ prop  = [α] ∃[β] α ≐ dom β ∨ α ≐ cod β 
  // Hom set between (dom α) and (cod β)
  hom: {α: Mor, β: Mor} tp ❙


// https://ncatlab.org/nlab/show/category#OneCollectionOfMorphisms ❚
theory CategoryWithOneCollection =
  include ?Option 
  include ?ObjectLessComposition 

  obj: tp 
  dom: Mor ⟶ tm obj 
  cod: Mor ⟶ tm obj 

  id: tm obj ⟶ Mor 

  ax_dom_preserved: {f, g} ⊦ map (g ∘ f) dom ≡ dom f 
  ax_cod_preserved: {f, g} ⊦ map (g ∘ f) cod ≡ cod g 

  ax_identities_dom_cod: {a} ⊦ dom (id a) ≐ a ∧ cod (id a) ≐ a 

  ax_comp_defined: {f, g} ⊦ cod f ≐ dom g ⇒ (g ∘ f)↓ 

  ax_associativity: {f, g, h} ⊦ (dom g ≐ cod f ∧ dom h ≐ cod g) ⇒ bothDefEq ((h ∘ g) ?∘ f) (h ∘? (g ∘ f)) 


// https://ncatlab.org/nlab/show/category#AFamilyOfCollectionsOfMorphisms ❚
theory CategoryWithHomSetsSFOL =
  obj: tp 

  hom: {dom: tm obj, cod: tm obj} tp 
  Hom: tm obj ⟶ tm obj ⟶ type  = [a, b] tm (hom a b) 
  id: {a} Hom a a 
  compositionABC: {x, y, z} Hom x y ⟶ Hom y z ⟶ Hom x z  # 5  4 prec 200 

  associativity: {a, b, c, d, f: Hom a b, g: Hom b c, h: Hom c d} ⊦ h ∘ (g ∘ f) ≐ (h ∘ g) ∘ f

  ax_identityLeftNeutral : {a, b, f: Hom a b} ⊦ (id b) ∘ f ≐ f 
  ax_identityRightNeutral: {a, b, f: Hom a b} ⊦ f ∘ (id a) ≐ f 


// view blah: ObjectLessCategory -> CategoryWithHomSetsSFOL =
  include ?Option ❙
  // mor = ? ❙

namespace latin:/

fixmeta ?TypedEquality

theory Collection =
  include ?EndoMagma
  include ?EndoNeutral

  singleton : {a} tm a ⟶ tm &a# S 2 prec 60
  cons : {a} tm a ⟶ tm &a ⟶ tm &a= [a,x,xs] S x ∘ xs


theory ListSpec =
  include ?Collection
  include ?EndoMonoid


theory MultisetSpec =
  include ?ListSpec
  include ?EndoCommutative


theory FiniteSetSpec =
  include ?MultisetSpec
  include ?EndoIdempotent


theory OptionSpec =
  include ?ListSpec
  include ?EndoFirstNonNeutral


theory Lists =
  structure list : ?ListSpec =
    applyType # List 1
    op # 2 concat 3
    e # nil %I1 
    singleton # list 2
 


theory Multisets =
  structure multiset : ?MultisetSpec =
    applyType # Multiset 1
    op # 2 munion 3
    e # mempty %I1 
    singleton # multiset 2
 


theory FiniteSets =
  structure finset : ?FiniteSetSpec =
    applyType # FinSet 1
    op # 2 union 3
    e # empty %I1 
    singleton # finset 2
 


theory Options =
  structure option : ?OptionSpec =
    applyType # Option 1
    op # 2 orelse 3
    e # none %I1 
    singleton # option 2
 

namespace latin:/powertypes

fixmeta ur:?LF

theory CongruenceTypes =
  include ☞latin:/?TypedEquality
  include ☞latin:/?EquivalenceND
  
  Cong : tp ⟶ tp# Cong 1 prec 100
  is_cong : {A} tm Cong A  ⟶ tm A ⟶ tm A ⟶ prop# 3  4 mod 2 prec 30
  cong  : {A} (tm A ⟶ tm A ⟶ prop) ⟶ tm Cong A# cong 2 prec 50
  
  compute : {A,R,x,y: tm A} ⊦ x ≡ y mod (cong R) ⇔ R x y
  expand  : {A,C:tm Cong A} ⊦ C ≐ cong [x,y] x≡y mod C
 
  cong_refl : {A, C: tm Cong A, x} ⊦ x≡x mod C
  cong_sym  : {A, C: tm Cong A, x, y} ⊦ x≡y mod C ⟶ ⊦ y≡x mod C
  cong_trans : {A, C: tm Cong A, x,y,z} ⊦ x≡y mod C ⟶ ⊦ y≡z mod C ⟶  ⊦ x≡z mod C

namespace latin:/

fixmeta ?TypedEqualityND

theory TypeOperator =
  applyType: tp ⟶ tp# & 1 prec 60


theory EndoFunctor =
  include ?TypeOperator
  applyFun: {a,b} (tm a ⟶ tm b) ⟶ tm &a ⟶ tm &b# 4 map 3 prec 50
  applyId : {a,xs: tm &a} ⊦ xs map ([x] x) ≐ xs
  applyComp : {a,b,c,f:tm a ⟶ tm b, g: tm b ⟶ tm c, xs: tm &a} ⊦ xs map f map g ≐ xs map [x] g (f x)


fixmeta ?HOLND

theory Category = 
  obj: type
  hom: obj ⟶ obj ⟶ tp
  Hom: obj ⟶ obj ⟶ type= [a,b] tm (hom a b)
  id : {a} Hom a a
  comp : {a,b,c} Hom a b ⟶ Hom b c ⟶ Hom a c# 4 ; 5 prec 50

  neutLeft : {a,b,f:Hom a b} ⊦ (id a);f ≐ f
  neutRight : {a,b,f:Hom a b} ⊦ f;(id b) ≐ f
  assoc: {a,b,c,d, f:Hom a b, g:Hom b c, h:Hom c d} ⊦ f;(g;h) ≐ (f;g);h 


/T View currently not total ❚
implicit view CategoryOfTypes : ?Category  ?HOLND =
  obj = tp
  hom = [a,b] a→b
  id = [a] λ[x]x
  comp = [a,b,c,f,g] λ[x] g@(f@x)


theory InternalEndoFunctor =
  include ?TypeOperator
  fmap : {a,b} tm a→b ⟶ tm &a→&b# fmap 3 prec 50
  fmapApply : {a,b} tm a→b ⟶ tm &a ⟶ tm &b= [a,b,f,x] (fmap f)@x# 3 <$> 4
  fmapId : {a} ⊦ fmap (id a) ≐ id (&a)
  fmapComp : {a,b,c,f:tm a→b,g:tm b→c} ⊦ fmap (f;g) ≐ (fmap f);(fmap g)
  
  // Remaining implementation is missing
  realize ?EndoFunctor❙
  // applyFun = [a,b,f:tm a ⟶ tm b,x] (fmap λ f) @ x❙

namespace latin:/

fixmeta ?TypedEquality

theory EndoMagma =
  include ?EndoFunctor
  op : {a} tm &a ⟶ tm &a ⟶ tm &a# 2  3 prec 50


theory EndoSemigroup =
  include ?EndoMagma
  assoc: {a,x,y,z:tm &a} ⊦ (x∘y)∘z ≐ x∘(y∘z)
  
  assocR: {a,x,y,z:tm &a} ⊦ x∘(y∘z) ≐ (x∘y)∘z
        = [a,x,y,z] assoc sym

  assoc4:  {a,w,x,y,z:tm &a} ⊦ ((w∘x)∘y)∘z ≐ w∘(x∘(y∘z))
        =  [a,w,x,y,z] trans3 (assoc congT [u]u∘z) assoc (assoc congT [u]w∘u)
  assoc4R: {a,w,x,y,z:tm &a} ⊦ w∘(x∘(y∘z)) ≐ ((w∘x)∘y)∘z
        = [a,w,x,y,z] assoc4 sym
  assoc5: {a,v,w,x,y,z:tm &a} ⊦ (((v∘w)∘x)∘y)∘z ≐ v∘(w∘(x∘(y∘z)))
        = [a,v,w,x,y,z] trans4 (assoc4 congT [u]u∘z) assoc
                              (assoc congT [u]v∘u) (assoc congT [u]v∘(w∘u))


theory EndoCommutative =
  include ?EndoMagma
  comm: {a,x,y:tm &a} ⊦ x∘y ≐ y∘x


theory EndoNeutral =
  include ?EndoMagma
  e  : {a} tm &a# e %I1
  neutLeft: {a,x:tm &a} ⊦ e∘x ≐ x
  neutRight: {a,x:tm &a} ⊦ x∘e ≐ x


theory EndoIdempotent =
  include ?EndoMagma
  idempotent: {a,x:tm &a} ⊦ x∘x ≐ x


theory EndoFirstNonNeutral =
  include ?EndoNeutral
  firstNonNeutral: {a,x,y:tm &a} (⊦ x≐e ⟶ ↯) ⟶ ⊦ x∘y ≐ x


theory EndoMonoid =
  include ?EndoSemigroup
  include ?EndoNeutral


theory EndoCommSemigroup =
  include ?EndoSemigroup
  include ?EndoCommutative


theory EndoBand =
  include ?EndoSemigroup
  include ?EndoIdempotent


theory EndoCommMonoid =
  include ?EndoMonoid
  include ?EndoCommSemigroup


theory EndoSemilattice =
  include ?EndoBand
  include ?EndoCommSemigroup


theory EndoBoundedSemilattice =
  include ?EndoSemilattice
  include ?EndoCommMonoid

namespace latin:/

fixmeta ?HOLND

theory Applicative =
  include ?TypeOperator
  pure : {a} tm a ⟶ tm &a# pure 2 prec 60
  splat: {a,b} tm &(a→b) ⟶ tm &a ⟶ tm &b# 3 <*> 4 prec 50
  
  identity: {a,X:tm &a} ⊦ pure (id a) <*> X ≐ X
  homomorphism: {a,b,f:tm a→b,x} ⊦ pure f <*> pure x ≐ pure (f@x)
  interchange: {a,b,F:tm &(a→b), x} ⊦ F <*> pure x ≐ pure (applyTo x) <*> F
  composition: {a,b,c,F:tm &(a→b),G:tm &(b→c),X} ⊦ G <*> (F <*> X) ≐ pure (λ[f]λ[g]f;g) <*> F <*> G <*> X
  
  // The remaining implementation is missing ❙
  // realize ?InternalEndoFunctor❙
  // fmap = [a,b,f] λ[X] pure f <*> X❙


ref ?CategoryOfTypes

theory Monad =
  include ?TypeOperator
  Return : {a} tm a ⟶ tm &a# Return 2 prec 60
  Bind : {a,b} tm &a ⟶ (tm a ⟶ tm &b) ⟶ tm &b# 3 >>= 4 prec 50
  
  identLeft: {a,b,f:tm a ⟶ tm &b,x} ⊦ Return x >>= f ≐ f x
  identRight: {a,X: tm &a} ⊦ X >>= ([x] Return x) ≐ X
  assoc : {a,b,c,f:tm a ⟶ tm &b, g:tm b ⟶ tm &c,X} ⊦ X >>= f >>= g ≐ X >>= [x] (f x) >>= g
  
  // The remaining implementation is missing ❙
  // realize ?EndoFunctor❙
  // applyFun = [a,b,f,X] X >>= [x] Return (f x)❙


theory InternalMonad =
  include ?TypeOperator
  return : {a} tm a→&a
  bind : {a,b} tm &a→(a→&b)→&b

  structure laws : ?Monad =
    include ?TypeOperator
    Return = [a,x] (return a) @ x# Return 2 prec 60
    Bind = [a,b,X,F] (bind a b) @ X @ (λ F)# 3 >>= 4 prec 50
  

  // The remaining implementation is missing ❙
  // realize ?Applicative❙
  // pure = [a,x] Return x❙
  // splat = [a,b,F,X] F >>= [f] X >>= [x] Return (f@x)❙


// Assignments to neutrality and associativity axioms missing
// view KleisliCat : ?Category → ?InternalMonad =
  obj = tp❙
  hom = [a,b] a→&b❙
  id = [a] return a❙
  comp = [a,b,c,f,g] λ[x] Return x >>= ([x]f@x) >>= ([y]g@y)❘# 4 >=> 5 prec 50❙

namespace latin:/

fixmeta ur:?LF

theory SimpleFunctionTypes =
  include ?Types
  simpfun : tp ⟶ tp ⟶ tp# 1 %R→ 2 prec 50
  test = [a:tp] a → a → a


theory DependentFunctionTypes =
  include ?TypedTerms
  depfun : {A} (tm A ⟶ tp) ⟶ tp# Π 2 prec 40
  realize ?SimpleFunctionTypes
  simpfun = [A,B] Π [x: tm A] B


theory SoftDependentFunctionTypes =
  include ?SoftTypedTerms
  softfun : tp ⟶ (term ⟶ tp) ⟶ tp# Π 1 2 prec 40


theory SimpleFunctions =
  include ?SimpleFunctionTypes
  include ?TypedEquality
  simplambda: {A,B} (tm A ⟶ tm B) ⟶ tm A → B# λ 3 prec 40
  simpapply: {A,B} tm A → B ⟶ tm A ⟶ tm B# 3 @ 4 prec 50
  simpbeta : {A,B,F: tm A ⟶ tm B, X} ⊦ (λ F) @ X ≐ F X

  // should be an extra notation for simpapply❙
  apply1 : {a,b} tm a→b ⟶ (tm a ⟶ tm b)
         = [a,b,f] [x] f@x# %%prefix 2 1
  applyTo : {a,b} tm a ⟶ tm (a→b)→b= [a,b,x] λ[f]f@x# applyTo 3


theory DependentFunctions =
  include ?DependentFunctionTypes
  include ?TypedEquality
  deplambda: {A,B} ({x: tm A} tm B x) ⟶ tm Π B# λ 3 prec 40
  depapply: {A,B} tm Π B ⟶ {x: tm A} tm B x # 3 @ 4 prec 50
  depbeta : {A,B,F:{x:tm A} tm B x, X} ⊦ (λ F) @ X ≐ F X
  
  // realize ?SimpleFunctions❙
  // simplambda = [A,B,F] λ[x:tm A] F x❙
  // simpapply = [A,B,F,X] F @ X❙
  // simpbeta = [A,B,F,X] depbeta❙


theory SoftTypedFunctions =
  include ?Terms
  include ?SoftTypedEquality
  lambda: (term ⟶ term) ⟶ term# λ 1 prec 40
  apply : term ⟶ term ⟶ term# 1 @ 2 prec 50
  beta  : {F,X} ⊦ (λ F) @ X ≐ F X


theory SoftTypedSimpleFunctions =
  include ?SoftTypedTerms
  include ?SoftTypedFunctions
  include ?SimpleFunctionTypes
  fun_typing : {A,B,F} ({x} ⊦ x⦂A ⟶ ⊦ (F x)⦂B) ⟶ ⊦ λ F ⦂ A → B


theory SoftTypedDependentFunctions =
  include ?SoftTypedTerms
  include ?SoftTypedFunctions
  include ?SoftDependentFunctionTypes
  fun_typing : {A,B,F} ({x} ⊦ x⦂A ⟶ ⊦ (F x)⦂(B x)) ⟶ ⊦ λ F ⦂ Π A B


theory SimpleFunctionsEta =
  include ?SimpleFunctions
  eta: {A,B,F:tm A → B} ⊦ (λ[x] F @ x) ≐ F


theory DependentFunctionsEta =
  include ?DependentFunctions
  eta: {A,B, F:tm Π[x:tm A] B x} ⊦ (λ[x] F @ x) ≐ F


theory SoftTypedFunctionsEta =
  include ?SoftTypedFunctions
  eta: {F} ⊦ (λ[x] F @ x) ≐ F


theory SimpleFunctionsExtensionality =
  include ?SimpleFunctions
  exten: {A,B,F,G:tm A → B} ({x} ⊦ F@x ≐ G@x) ⟶ ⊦ F≐G


theory DependentFunctionsExtensionality =
  include ?DependentFunctions
  exten: {A,B, F,G:tm Π[x:tm A] B x} ({x} ⊦ F@x ≐ G@x) ⟶ ⊦ F≐G


theory SofttypedFunctionsExtensionality =
  include ?SoftTypedFunctions
  eta: {F,G} ({x} ⊦ F@x ≐ G@x) ⟶ ⊦ F≐G

namespace latin:/
import diagops scala://diagops.latin2

/T Declare operator constants

   Use an empty meta theory! E.g. if we used LF as a meta theory the notation
   would be parsed as LF-y.

theory TypeTheoryDiagramOperatorsSyntax =
  single_typeindexifier # SINGLE TYPEINDEXIFY 1 prec -2000000 
  multi_typeindexifier # MULTI TYPEINDEXIFY 1 prec -2000000 


theory TypeTheoryDiagramOperatorsSemantics : ur:?LF =
  include ☞http://cds.omdoc.org/urtheories?ModExp 
  rule diagops?ComputeSingleTypeIndexed 
  rule diagops?ComputeMultiTypeIndexed 


theory TypeTheoryDiagramOperators =
  include ?TypeTheoryDiagramOperatorsSyntax 
  include ?TypeTheoryDiagramOperatorsSemantics 


// theory TestMagma2 : ?TestMagmaMeta2 =
  U: tp ❙
  op: tm U ⟶ tm U ⟶ tm U ❘ # 1 ∘ 2 ❙


// diagram TestEndoMagmaSingle : ?TypeTheoryDiagramOperators := SINGLE TYPEINDEXIFY ?TestMagma2 ❚
// diagram TestEndoMagmaMulti : ?TypeTheoryDiagramOperators := MULTI TYPEINDEXIFY ?TestMagma2 ❚
namespace latin:/powertypes

import rules scala://parser.api.mmt.kwarc.info
rule rules:?MMTURILexer

fixmeta ur:?LF

theory PowerTypes =
  include ☞latin:/?TypedEqualityND
  include ☞latin:/?EquivalenceND
  
  power : tp ⟶ tp#  1 prec 100
  in    : {A} tm A  ⟶ tm ℘A ⟶ prop# 2  3 prec 30
  filter: {A} (tm A ⟶ prop) ⟶ tm ℘A# filter 2 prec 50
  
  compute : {A,P,x: tm A} ⊦ x ∈ filter P ⇔ P x
  expand  : {A,S:tm ℘A} ⊦ S ≐ filter[x]x∈S
  
  filterI : {A,P,x: tm A} ⊦ P x ⟶ ⊦ x ∈ filter P
  				= [A,P,x,p] compute equivEr p
  filterE : {A,P,x: tm A} ⊦ x ∈ filter P ⟶ ⊦ P x# 4 filterE  
  				= [A,P,x,p] compute equivEl p


theory Map = 
  include ?PowerTypes
  include ☞latin:/?ConjunctionND
  include ☞latin:/?TypedExistentialQuantificationND
  map : {A,B} (tm A ⟶ tm B) ⟶ tm ℘A ⟶ tm ℘B
      = [A,B,f,S] filter[b] ∃[a] a∈S ∧ (b ≐ f a)# 4 map 3 prec 40
  mapI : {A,B,f:tm A ⟶ tm B,S,x} ⊦ x ∈ S ⟶ ⊦ f x ∈ S map f
       = [A,B,f,S,x,p] filterI existsI x andI p refl
  mapE : {A,B,f:tm A ⟶ tm B,S,x,C} ⊦ x ∈ S map f ⟶ ({a} ⊦ a∈S ⟶ ⊦ x ≐ f a ⟶ ⊦C) ⟶ ⊦ C
       = [A,B,f,S,x,C,p,q] p filterE existsE [a,r] q a (r andEl) (r andEr)


theory Extensionality =
  include ?PowerTypes
  include ☞latin:/?TypedUniversalQuantificationND

  extensionality  : {A,S,T:tm ℘A} ⊦(∀[x:tm A] x∈S ⇔ x∈T) ⟶ ⊦ S≐T
  extensionalityI : {A,S,T:tm ℘A} ({x}⊦x∈S⟶⊦x∈T) ⟶ ({x}⊦x∈T⟶⊦x∈S) ⟶ ⊦ S≐T
                  = [A,S,T,f,g] extensionality (forallI [x] equivI ([p] f x p) ([q] g x q))
  eq_in_left : {A,S,T,x:tm A} ⊦ S≐T ⟶ ⊦ x∈S ⟶ ⊦ x∈T
        = [A,S,T,x,p,q] p congP ([u]x∈u) q
  eq_in_right : {A,S,T,x:tm A} ⊦ S≐T ⟶ ⊦ x∈T ⟶ ⊦ x∈S
        = [A,S,T,x,p,q] p sym congP ([u]x∈u) q


theory FiniteSets = 
  include ?PowerTypes
  include ☞latin:/?DisjunctionND
  singleton : {A} tm A ⟶ tm ℘A= [A,x] filter [u] u≐x# % 2 prec 100
  singletonI : {A,x: tm A} ⊦ x ∈ %x= [A,x] filterI refl 
  singletonE : {A,x,y: tm A} ⊦ x ∈ %y ⟶ ⊦ x≐y
  
  uopair : {A} tm A ⟶ tm A ⟶ tm ℘A= [A,x,y] filter [u]u≐x ∨ u≐y# 2 ,, 3 prec 40
  uopairI_left  : {A,x,y: tm A} ⊦ x ∈ x,,y= [A,x,y] filterI (refl orIl)
  uopairI_right : {A,x,y: tm A} ⊦ y ∈ x,,y= [A,x,y] filterI (refl orIr)
  uopairE : {A,x,y,u:tm A,C} ⊦ u ∈ x,,y ⟶ (⊦u≐x ⟶ ⊦ C) ⟶ (⊦u≐y ⟶ ⊦ C) ⟶ ⊦C
          = [A,x,y,u,C,p,q,r] p filterE orE q r


theory Subset =
  include ?PowerTypes
  include ?Extensionality
  include ☞latin:/?ImplicationND

  subset : {A} tm ℘A ⟶ tm ℘A ⟶ prop	
         = [A,S,T] ∀[x] x∈S ⇒ x∈T
         # 2  3 prec 30
  
  subsetI: {A,S,T} ({x: tm A} ⊦x∈S ⟶ ⊦ x∈T) ⟶ ⊦ S⊆T
         = [A,S,T,f] forallI [x] impI [p] f x p
  subsetE: {A,S,T,x:tm A} ⊦ S⊆T ⟶ ⊦ x∈S ⟶ ⊦ x∈T
         = [A,S,T,x,p,q] p forallE x impE q
  subset_refl : {A,S:tm ℘A} ⊦ S⊆S
              = [A,S] subsetI [x,p]p
  subset_trans : {A,R,S,T:tm ℘A} ⊦ R⊆S ⟶ ⊦ S⊆T ⟶ ⊦ R⊆T
               = [A,R,S,T,p,q] subsetI [x,r] subsetE q (subsetE p r)
  subset_antisym : {A,S,T:tm ℘A} ⊦ S⊆T ⟶ ⊦ T⊆S ⟶ ⊦ S≐T
                 = [A,S,T,p,q] extensionalityI ([x,r] subsetE p r) ([x,r] subsetE q r)


theory FullSet =
  include ?PowerTypes
  include ☞latin:/?TruthND

  full  : {A} tm ℘A
        = [A] filter [x] true
        # fullset %I1 prec 50
  fullI : {A,x} ⊦ x ∈ full A  
  		  = [A,x] filterI trueI


theory EmptySet =
  include ?PowerTypes
  include ☞latin:/?FalsityND

  empty : {A} tm ℘A
        = [A] filter [x] false
        #  %I1 prec 50
  emptyE : {A,x} ⊦ x ∈ empty A ⟶ ↯ 
  			 = [A,x,p] p filterE falseE
  			 # emptyE 3


theory Complement =
  include ?PowerTypes
  include ☞latin:/?NegationND

  compl : {A} tm ℘A ⟶ tm ℘A 
        = [A,S] filter [x] ¬ x∈S 
        #  2 prec 50
  complI : {A,S,x:tm A} (⊦x∈S ⟶ ↯) ⟶ ⊦ x∈∁S 
  			 = [A,S,x,p] filterI notI p
  			 # complI 4
  complE : {A,S,x:tm A} ⊦ x∈∁S ⟶ ⊦ x∈S ⟶ ↯ 
  			 = [A,S,x,p,q] p filterE notE q # complE 4 5


theory Intersection =
  include ?PowerTypes
  include ☞latin:/?ConjunctionND

  inter : {A} tm ℘A ⟶ tm ℘A ⟶ tm ℘A 
  			= [A,S,T] filter [x] x∈S ∧ x∈T
  			# 2  3 prec 40
  interEl : {A,S,T,x:tm A} ⊦ x ∈ S∩T ⟶ ⊦ x∈S
  				 = [A,S,T, x, p] p filterE andEl
  interEr : {A,S,T,x:tm A} ⊦ x ∈ S∩T ⟶ ⊦ x∈T
  				 = [A,S,T,x,p] p filterE andEr
  interI  : {A,S,T,x:tm A} ⊦ x∈S ⟶ ⊦ x∈T ⟶ ⊦ x ∈ S∩T
  				 = [A,S,T,x,p,q] filterI andI p q


theory Union =
  include ?PowerTypes
  include ☞latin:/?DisjunctionND

  union : {A} tm ℘A ⟶ tm ℘A ⟶ tm ℘A  
  				= [A,S,T] filter [x] x∈S ∨ x∈T
  				# 2  3 prec 40
  unionIl: {A,S,T,x:tm A} ⊦ x∈S ⟶ ⊦ x ∈ S∪T
         = [A,S,T,x,p] filterI (p orIl)
  unionIr: {A,S,T,x:tm A} ⊦ x∈T ⟶ ⊦ x ∈ S∪T
         = [A,S,T,x,p] filterI (p orIr)
  unionE : {A,S,T,x:tm A,C} ⊦ x ∈ S∪T ⟶ (⊦x∈S⟶⊦C) ⟶ (⊦x∈T⟶⊦C) ⟶ ⊦ C
  			 = [A,S,T,x,C,p,q,r] p filterE orE q r


theory BigIntersection =
  include ?PowerTypes
  include ☞latin:/?ImplicationND
  include ☞latin:/?TypedUniversalQuantificationND

  biginter : {A} tm ℘℘A ⟶ tm ℘A  
    			 = [A,K] filter [x] ∀[S] S∈K ⇒ x∈S 
    			 #  2 prec 45
  biginterI : {A,K,x:tm A} ({S}⊦S∈K⟶⊦x∈S) ⟶ ⊦ x∈⋂K  
  				  = [A,K,x,f] filterI (forallI [S] impI [p] f S p)
  biginterE : {A,K,x:tm A,S} ⊦ x∈⋂K ⟶ ⊦S∈K ⟶ ⊦x∈S 
  				  = [A,K,x,S,p,q] p filterE forallE S impE q


theory BigUnion =
  include ?PowerTypes
  include ☞latin:/?ConjunctionND
  include ☞latin:/?TypedExistentialQuantificationND

  bigunion : {A} tm ℘℘A ⟶ tm ℘A  
  				 = [A,K] filter [x] ∃ [S] S∈K ∧ x∈S 
  				 #  2 prec 45
  bigunionI : {A,K,S,x:tm A} ⊦ S∈K ⟶ ⊦ x∈S ⟶ ⊦ x∈⋃K  
  				  = [A,K,S,x,p,q] filterI (existsI S (andI p q))
  bigunionE : {A,K,x:tm A,C} ⊦ x∈⋃K ⟶ ({S}⊦S∈K⟶⊦x∈S⟶⊦C) ⟶ ⊦ C 
  				  = [A,K,x,C,p,f] p filterE existsE [S,rs] f S (rs andEl) (rs andEr)


theory Lattice =
  include ?Extensionality
  include ?Subset
  include ?FullSet
  include ?EmptySet
  include ?Complement
  include ?Intersection
  include ?Union
  include ?BigIntersection
  include ?BigUnion


theory SubsetRules =
  include ?Lattice

  subset_full : {A,S} ⊦ S ⊆ full A
              = [A,S] subsetI [x,p] fullI
  subset_empty : {A,S} ⊦ empty A ⊆ S
               = [A,S] subsetI [x,p] (emptyE p) inconE

  subset_union_left : {A,S,T: tm ℘A} ⊦ S ⊆ S ∪ T
                    = [A,S,T] subsetI [x,p] unionIl p
  subset_union_right : {A,S,T: tm ℘A} ⊦ T ⊆ S ∪ T
                    = [A,S,T] subsetI [x,p] unionIr p
  subset_union_lub : {A,S,T,C: tm ℘A} ⊦ S ⊆ C ⟶ ⊦ T ⊆ C ⟶ ⊦ S ∪ T ⊆ C
                   = [A,S,T,C,s,t] subsetI [x,st] unionE st ([xs] subsetE s xs) ([xt] subsetE t xt)
 
  subset_inter_left : {A,S,T: tm ℘A} ⊦ S ∩ T ⊆ S
                    = [A,S,T] subsetI [x,p] interEl p
  subset_inter_right : {A,S,T: tm ℘A} ⊦ S ∩ T ⊆ T
                    = [A,S,T] subsetI [x,p] interEr p
  subset_inter_glb : {A,S,T,C: tm ℘A} ⊦ C ⊆ S ⟶ ⊦ C ⊆ T ⟶ ⊦ C ⊆ S ∩ T
                   = [A,S,T,C,s,t] subsetI [x,xc] interI (subsetE s xc) (subsetE t xc)

  subset_bigunion : {A,K,S: tm ℘A} ⊦ S ∈ K ⟶ ⊦ S ⊆ ⋃ K
                  = [A,K,S,p] subsetI [x,q] bigunionI p q 
  subset_bigunion_lub : {A,K,C: tm ℘A} ({S} ⊦ S ∈ K ⟶ ⊦ S ⊆ C) ⟶ ⊦ ⋃ K ⊆ C
                      = [A,K,C,f] subsetI [x,p] bigunionE p [S,q,r] subsetE (f S q) r
  
  subset_biginter : {A,K,S: tm ℘A} ⊦ S ∈ K ⟶ ⊦ ⋂ K ⊆ S
                  = [A,K,S,p] subsetI [x,q] biginterE q p 
  subset_biginter_glb : {A,K,C: tm ℘A} ({S} ⊦ S ∈ K ⟶ ⊦ C ⊆ S) ⟶ ⊦ C ⊆ ⋂ K
                      = [A,K,C,f] subsetI [x,p] biginterI [S,q] subsetE (f S q) p
  subset_compl : {A,S,T: tm ℘A} ⊦ S⊆T ⟶ ⊦ ∁T⊆∁S
               = [A,S,T,p] subsetI [x,q] complI [r] complE q (subsetE p r)


theory ComplementRules =
  include ?Lattice
  include ?SubsetRules
  compl_empty : {A} ⊦ ∁(empty A) ≐ full A
              = [A] extensionalityI ([x,p] fullI) ([x,p] complI [q] emptyE q)
  compl_full  : {A} ⊦ ∁(full A) ≐ empty A
              = [A] extensionalityI ([x,p] (complE p fullI) inconE) ([x,p] (emptyE p) inconE)
  compl_union : {A, S,T: tm ℘A} ⊦ ∁(S∪T) ≐ ∁S ∩ ∁T
              = [A,S,T] extensionalityI
                    ([x,p] interI (complI [q] complE p (unionIl q))
                                  (complI [q] complE p (unionIr q))
                    )
                    ([x,p] complI [q,C] unionE q ([r] complE (interEl p) r inconE)
                                                 ([r] complE (interEr p) r inconE)
                    )

  inter_compl : {A,S} ⊦ S ∩ ∁S ≐ empty A
              = [A,S] extensionalityI ([x,p] (complE (interEr p) (interEl p)) inconE)
                                      ([x,p] (emptyE p) inconE)

  compl_not : {A,S,x:tm A} ⊦¬x∈S ⟶ ⊦x∈∁S= [A,S,x,p] complI [q] p notE q

  include ☞latin:/?PLND
  union_compl : {A,S} ⊦ S ∪ ∁S ≐ full A
              = [A,S] extensionalityI
                   ([x,p] fullI)
                   ([x,p] tnd orE ([q] unionIl q) ([q] unionIr (compl_not q)))
  compl_tnd   : {A,S,x: tm A} ⊦ x∈S ∨ x∈∁S
              = [A,S,x] (eq_in_right union_compl fullI) filterE
  
  compl_inter : {A, S,T: tm ℘A} ⊦ ∁(S∩T) ≐ ∁S ∪ ∁T
              = [A,S,T] extensionalityI
                    ([x,p] compl_tnd orE ([q] compl_tnd orE ([r] complE p (interI q r) inconE) ([r] unionIr r)) ([r] unionIl r))
                    ([x,p] unionE p ([q] subsetE (subset_compl subset_inter_left) q)
                                    ([q] subsetE (subset_compl subset_inter_right) q)
                    )
  
  compl_compl : {A, S:tm ℘A} ⊦ ∁∁S ≐ S
              = [A,S] extensionalityI ([x,p] compl_tnd orE ([q] q) ([q] complE p q inconE)) ([x,p] complI [q] complE q p)


theory PowerSFOL =
   include ☞latin:/?SFOLEQND
   include ?PowerTypes
   include ?FiniteSets
   include ?Map
   include ?Lattice
   include ?SubsetRules
   include ?ComplementRules

namespace latin:/

fixmeta ur:?LF

theory PredicateSubtypes =
  include ?Subtyping
  include ?SubtypeInjections
  
  predsub : {A} (tm A ⟶ prop) ⟶ tp#  2   prec -10050
  in      : {A,P, x:tm A}  ⊦ P x ⟶ tm ⦃P⦄
  
  predsub_sub: {A,P: tm A ⟶ prop} ⊦ ⦃P⦄ ⪽ A
  predsub_prop: {A,P: tm A ⟶ prop, x: tm ⦃P⦄} ⊦ P (x↑predsub_sub)

namespace latin:/

fixmeta ur:?LF

theory SimpleProductTypes =
  include ?Types
  simpprod : tp ⟶ tp ⟶ tp# 1 × 2 prec 50


theory DependentProductTypes =
  include ?TypedTerms
  depprod : {A} (tm A ⟶ tp) ⟶ tp# Σ 2 prec 40
  realize ?SimpleProductTypes
  simpprod = [A,B] Σ [x: tm A] B


theory SoftDependentProductTypes =
  include ?SoftTypedTerms
  softprod : tp ⟶ (term ⟶ tp) ⟶ tp# Σ 1 2 prec 40


theory SimpleProducts =
  include ?SimpleProductTypes
  include ?TypedEquality
  simppair: {A,B} tm A ⟶ tm B ⟶ tm A × B# 3 , 4 prec 50
  simppi1 : {A,B} tm A × B ⟶ tm A# 3  prec 60
  simppi2 : {A,B} tm A × B ⟶ tm B# 3  prec 60
  
  compute1 : {A,B,a:tm A,b:tm B} ⊦ (a,b)₁ ≐ arole Simplify
  compute2 : {A,B,a:tm A,b:tm B} ⊦ (a,b)₂ ≐ brole Simplify


theory DependentProducts =
  include ?DependentProductTypes
  include ?TypedEquality
  include ?Transport
  deppair: {A,B, a: tm A} tm B a ⟶ tm Σ B# 3 , 4 prec 50
  deppi1 : {A,B: tm A ⟶ tp} tm Σ B ⟶ tm A # 3  prec 60
  deppi2 : {A,B, u: tm Σ [x: tm A] B x} tm B (u₁)# 3  prec 60

  compute1 : {A, B, a: tm A, b} ⊦ ((a,b):tm Σ B)₁ ≐ arole Simplify
  // compute2 : {A, B: tm A ⟶ tp, a, b} ⊦ (a,b: tm Σ B)₂↑(compute1 congTp B) ≐ b❘role Simplify❙


theory SoftTypedProducts =
  include ?Terms
  include ?SoftTypedEquality
  pair: term ⟶ term ⟶ term# 1 , 2 prec 50
  pi1 : term ⟶ term# 1  prec 60
  pi2 : term ⟶ term# 1  prec 60

  compute1 : {a,b} ⊦ (a,b)₁ ≐ arole Simplify
  compute2 : {a,b} ⊦ (a,b)₂ ≐ brole Simplify


theory SoftTypedSimpleProducts =
  include ?SoftTypedTerms
  include ?SoftTypedProducts
  include ?SimpleProductTypes
  fun_typing : {A,B,a,b} ⊦ a⦂A ⟶ ⊦ b⦂B ⟶ ⊦ (a,b) ⦂ A × B


theory SoftTypedDependentProducts =
  include ?SoftTypedTerms
  include ?SoftTypedProducts
  include ?SoftDependentProductTypes
  fun_typing : {A,B,a,b} ⊦ a⦂A ⟶ ⊦ b⦂(B a) ⟶ ⊦ (a,b) ⦂ Σ A B


theory SimpleProductsExpand =
  include ?SimpleProducts
  expand: {A,B,u:tm A × B} ⊦ (u₁,u₂) ≐ u


theory DependentProductsExpand =
  include ?DependentProducts
  expand: {A,B, u:tm Σ[x:tm A] B x} ⊦ (u₁,u₂) ≐ u


theory SoftTypedProductsExpand =
  include ?SoftTypedProducts
  expand: {u} ⊦ (u₁,u₂) ≐ u


theory SimpleProductsExtensionality =
  include ?SimpleProducts
  exten: {A,B,u,v:tm A × B} ⊦ u₁≐v₁ ⟶ ⊦ u₂≐v₂ ⟶ ⊦ u≐v


theory DependentProductsExtensionality =
  include ?DependentProducts
  exten: {A,B,u,v:tm Σ[x:tm A] B x} {p: ⊦ u₁≐v₁} ⊦ u₂↑(p congTp B)≐v₂ ⟶ ⊦ u≐v


theory SoftTypedProductsExtensionality =
  include ?SoftTypedProducts
  exten: {u,v} ⊦ u₁ ≐ v₁ ⟶ ⊦ u₂≐v₂ ⟶ ⊦ u≐v

namespace latin:/

fixmeta ur:?LF

import rules scala://mmt.kwarc.info


theory Strings =
  string : type
  rule rules/lf?Realize string rules/api/uom?StandardString
  
  concat : string ⟶ string ⟶ string
  rule rules/lf?Realize concat rules/api/uom?StringOperations/Concat
  
  test : string = "test"


theory CTTQE = 
  include ?TypedLogic
  include ?Strings
  include ?SimpleFunctions
  include ?UndefinedTypedTerms

  Quotation: tp# ε
  rule rules/lf?Realize (tm Quotation) rules/api/uom?TermLiteral 
  
  quote #  1  prec -10050

  eval : tm ε ⟶ {a:tp} tm a #  1 % 2  prec -10050  
  
  const: string ⟶ tp ⟶ tm ε# const 1
  var: string ⟶ tp ⟶ tm ε
  application: tm ε ⟶ tm ε ⟶ tm ε# 1 app 2
  abstraction: string ⟶ tp ⟶ tm ε ⟶ tm ε# abs 1 % 2 . 3
  quotation: tm ε ⟶ tm ε# quo 1 
  
  // rule ComputeApply❙


theory Example =
  include ?CTTQE

  

namespace latin:/

fixmeta ur:?LF

theory TypeEquality =
  include ?TypedLogic
  structure tpeq : ?EqualityND =
    include ?Logic
    term = tp
    equal # 1  2 prec 50   
  


theory Transport =
  include ?TypeEquality
  include ?TypedEqualityND
  
  congTp : {A, X,Y} ⊦ X≐Y ⟶ {B: tm A ⟶ tp} ⊦ B X ≛ B Y# 4 congTp 5  
  
  transport : {A, B} ⊦ A ≛ B ⟶ tm A ⟶ tm B# 4  3 prec 70
  transport_refl: {A,X: tm A} ⊦ X↑tpeq/refl ≐ X

  // Doesn't typecheck:
  transport_trans: {A,B,C, X: tm A, p:⊦ A ≛ B, q: ⊦ B ≛ C} ⊦ X↑p↑q ≐ X↑(tpeq/eq/trans p q)❙

namespace latin:/

view TypeErasTerms : ?TypedTerms  ?SoftTypedTerms =
  include ?Types
  tm = [A] term


view TypeErasEquality : ?TypedEquality  ?SoftTypedEquality =
  include ?TypeErasTerms
  include ?Logic
  equal = [A,x,y] x≐y


// View currently not total
view TypeErasSimpleFunctions : ?SimpleFunctions → ?SoftTypedSimpleFunctions =
  include ?TypeErasTerms❙
  include ?TypeErasEquality❙
  simpfun = [A,B] A → B❙
  simplambda = [A,B,F] λ F❙
  simpapply = [A,B,F,X] F @ X❙


// View currently not total
view TypeErasDependentFunctions : ?DependentFunctions → ?SoftTypedDependentFunctions =
  include ?TypeErasTerms❙ 
  include ?TypeErasEquality❙
  depfun = [A,B] Π A B❙
  deplambda = [A,B,F] λ F❙
  depapply = [A,B,F,X] F @ X❙

namespace latin:/

fixmeta ur:?LF

theory UndefinedTerms =
  include ?UntypedLogic
  defined : term ⟶ prop# 1  prec 70
  
  strict_equal : term ⟶ term ⟶ prop # 1  2 prec 50 


theory UndefinedTypedTerms =
  include ?TypedLogic
  defined : {A} tm A ⟶ prop# 2  prec 70

  strict_equal : {A} tm A ⟶ tm A ⟶ prop# 2  3 prec 50 


theory UndefinedSoftTypedTerms =
  include ?SoftTypedTerms
  defined : term ⟶ tp ⟶ prop# 1  2 prec 50

namespace http://gl.mathhub.info/MMT/LFX/Coproducts 
import rules scala://Coproducts.LFX.mmt.kwarc.info

fixmeta http://cds.omdoc.org/mmt?mmt 

theory Symbols =
	Coprod # 1  prec -10000
	inl # 1 ↪l 2 prec -5 
	inr # 2 r↩ 1 prec -5 
	coprodmatch # 2 match V1 . 3| to 4 %I5 prec -9000
	coprodmatch2 # 2 match 5 , V1 . 3| to 4 prec -9001

	
theory FuncaddSymbol =
	Addfunc # 1 prec 0

	
theory SimpleRules =
   rule rules?CoprodTerm 
   rule rules?inlTerm 
   rule rules?inrTerm 
   rule rules?MatchTerm 
   rule rules?MatchComp 
   // rule rules?MatchEquality ❙
   rule rules?CoprodSubType 


theory TypedCoproduct : ur:?TermsTypesKinds =
	include ?Symbols 
  include ?SimpleRules 



theory FuncaddRules =
	rule rules?AddFuncComp 


theory LFCoprod =
	include ?FuncaddSymbol 
	include ?FuncaddRules 
	include ?TypedCoproduct 
	include ☞ur:?LF 

	
	
namespace http://gl.mathhub.info/MMT/LFX/Datatypes 
import rules scala://datatypes.LFX.mmt.kwarc.info

fixmeta http://cds.omdoc.org/mmt?mmt 

theory ListSymbols =
   ListType # List 1 prec -500 
   nil 
   ls # ls 1, prec -500
   append # 1 ++ 2 
   map # 1 map 2 


theory ListRules =
	rule rules?ListTypeRule 
	rule rules?ListVariance 
	rule rules?ListCheckRule 
	rule rules?AppendType 
	rule rules?MapType 
	rule rules?MapComp 


theory LFLists =
	include ?ListSymbols 
	include ?ListRules 
	include ☞ur:?LF 


theory LetSymbol =
    Let # Let V1 = 2 in 3 prec -5000 


theory LetRules =
    rule rules?LetRule 


theory LFLet =
    include ?LetSymbol 
    include ?LetRules 
    include ☞ur:?LF 


theory SubSymbol =
    substitute # 1 sub 2 / 3 prec -5000 


theory SubRules =
    rule rules?SubRule 


theory LFSub =
    include ?SubSymbol 
    include ?SubRules 
    include ☞ur:?LF 

namespace http://gl.mathhub.info/MMT/LFX/Equality 
import rules scala://Equality.LFX.mmt.kwarc.info

fixmeta http://cds.omdoc.org/mmt?mmt 

theory Symbols =
	eqtype # 1  2 on 3 prec -500  role Eq 
	refl # refl 1
	ind # ind 4 . V1 , V2 , V3  5 to 6


theory Rules =
	rule rules?EqFormation 
	rule rules?ReflIntro 
	rule rules?EqIndElim 
	rule rules?EqIndComp 

	
theory TypedEquality =
  include ☞ur:?TermsTypesKinds 
  include ?Symbols 
  include ?Rules 

	
theory LFEquality =
	include ?TypedEquality 
	include ☞ur:?LF 

namespace http://gl.mathhub.info/MMT/LFX/Finite 
import rules scala://FiniteTypes.LFX.mmt.kwarc.info

fixmeta http://cds.omdoc.org/mmt?mmt 

theory Symbols =
  include ☞ur:?LambdaPi 
	emptyType #  
	emptyFun # 1 ∅f 2 prec -900 
	UNIT 
	unite #  


theory TypedRules =
  include ☞ur:?Typed 
  include ☞ur:?Kinded 
  rule rules?EmptyTypeFormation 
  rule rules?UnitTypeFormation 
  rule rules?UnitIntro 
  rule rules?EmptyElim 
  rule rules?UnitIrrelevance 


theory SubTypedRules =
	include ?TypedRules 
	rule rules?EmptySub 
	rule rules?EmptyFunComputation 


theory EnumSymbols =
	ENUM # ENUM 1 
	CASE # CASE 1 


theory EnumRules =
   include ☞ur:?NatLiteralsOnly 
   include ?SubTypedRules 
   rule rules?EnumFormation 
   rule rules?CaseIntroduction 
   rule rules?CaseTyping 
   rule rules?CaseSubtyping 


theory EnumCoprodRules =
	include ?EnumRules 
	include ☞http://gl.mathhub.info/MMT/LFX/Coproducts?TypedCoproduct 
	rule rules?EnumComputation 
	rule rules?CaseComputation 


theory DefinedUnitRules =
	include ?TypedRules 
	rule rules?UnitComputation 
	rule rules?UnitElemComputation 


theory LFFiniteBase =
  include ?Symbols 
  include ?EnumSymbols 
  include ☞ur:?LF 
  include ?DefinedUnitRules 
  include ?EnumRules 
  include ☞ur:?Ded 
  include ☞ur:?NatRels 

	
theory LFFinite =
  include ?LFFiniteBase 
  include ?EnumCoprodRules 
	include ☞http://gl.mathhub.info/MMT/LFX/Coproducts?LFCoprod 

namespace http://gl.mathhub.info/MMT/LFX/IntersectionTypes 

import rules scala://LFIntersectionTypes.LFX.mmt.kwarc.info 
import lfrules scala://lf.mmt.kwarc.info

fixmeta http://cds.omdoc.org/mmt?mmt 

theory Symbols =
	typeintersection # 1 prec -9999 


theory Rules =
  include ☞ur:?TermsTypesKinds 

  rule rules?IntersectionTypeRule 
  rule rules?IntersectionTyping 
  rule rules?IntersectionSubtypeRuleLeft 
  rule rules?IntersectionSubtypeRuleRight 

	
theory LFIntersectionTypes = 
	include ☞ur:?LambdaPi 
	include ?Symbols 
	include ?Rules 
	
	rule lfrules?PiType
	rule lfrules?PiTerm
	// rule lfrules?ApplyTerm❙
	rule lfrules?LambdaTerm
   
	rule lfrules?Beta
	rule lfrules?Extensionality
	rule lfrules?PiCongruence
	rule lfrules?LambdaCongruence
   
	rule lfrules?Solve
	rule lfrules?SolveType

	rule lfrules?TheoryTypeWithLF
   
	rule lfrules?PiIntroduction
	rule lfrules?ForwardPiElimination
	rule lfrules?BackwardPiElimination
	rule lfrules?LFHOAS
	rule rules?ApplyIntersection 

namespace http://gl.mathhub.info/MMT/LFX/Records 
import rules scala://Records.LFX.mmt.kwarc.info
import rules2 scala://LFX.mmt.kwarc.info 

fixmeta http://cds.omdoc.org/mmt?mmt 

theory Symbols =
	include ☞http://cds.omdoc.org/urtheories?ModExp 
	
  Rectype # {' L1Td, '} prec -10000 
  Recexp  # [' L1Dd, '] prec -12000 
  Getfield # 1 . L2 prec 100000 
  ModelsOf # Mod 1 prec -1000 
  // ModelsOfUnary # Mod 1 prec -999 ❙
  // AsInstance # AsInstance 1 prec -1000 ❙
  RecordMerge # 1 prec 0


  
theory Rules =
  rule rules?GetFieldComp 
  // rule rules?GetFieldInType ❙
  rule rules?GetfieldTerm 
  rule rules?RecEquality 
  rule rules?RecExpCongruence 
  rule rules?RecordExpTerm 
  rule rules?RecordTypeTerm 
  rule rules?RecSubtype 
  rule rules?RecTypeCheck 
  rule rules?RecTypeCongruence 
  rule rules?CanonicalSolution
  // rule rules?ModelsRule ❙
  rule rules?ModelsInference 
  rule rules?ModelsChecking 
  rule rules?Instance 
  rule rules?ExtendInstance 
  rule rules?RecordMergeInference 
  rule rules?MergeCheck 


theory TypedRecords =
	include ☞ur:?TermsTypesKinds 
	include ?Symbols 
	include ?Rules 

  
theory LFRecords =
	include ☞ur:?LF 
	include ?TypedRecords 

namespace http://gl.mathhub.info/MMT/LFX/Sigma 
import rules scala://Sigma.LFX.mmt.kwarc.info

fixmeta http://cds.omdoc.org/mmt?mmt 

theory Symbols =
   Sigma   # Σ V1T, . 2   prec -10000 
   Product # 1×           prec  -9990
   Tuple   #  1, 				prec -10000 
   Projl   # πl 1						prec -900 
   Projr   # πr 1						prec -900 


theory Rules =
   rule rules?SigmaTerm 
   rule rules?TupleTerm 
   rule rules?Projection1Term 
   rule rules?Projection2Term 
   rule rules?SigmaType 
   rule rules?SigmaEquality 
   rule rules?TupleEquality 
   rule rules?Projection1Beta 
   rule rules?Projection2Beta 
   rule rules?SigmaSubtype 

   
theory TypedSigma : ur:?TermsTypesKinds =
	include ?Symbols 
	include ?Rules 

   
theory LFSigma =
	include ?TypedSigma 
	include ☞ur:?LF 

namespace http://gl.mathhub.info/MMT/LFX/Subtyping 

import rules scala://Subtyping.LFX.mmt.kwarc.info

fixmeta http://cds.omdoc.org/mmt?mmt 

theory PiRule =
  rule rules?PiRule 

  
theory LFWithVariance =
	include ☞ur:?LF 
	include ?PiRule 


theory SubSymbol =
	subtypeOf # %n 1 prec -9996 

  
theory SubRules =
	rule rules?SubUniverseRule 
	rule rules?SubUniverseType 
  rule rules?SubtypeOfRule 
  rule rules?SubtypeOfTypeRule 

  
theory LFPowerTypes =
	include ?SubSymbol 
	include ?SubRules 
	include ?LFWithVariance 

	

theory JudgmentSymbol =
	subtypeJudge # 1 <* 2 prec -9995 

  
theory JudgmentRules =
  rule rules?SubJudgUniverseType 
  // rule rules?SubJudgRule ❙

  
theory LFSubJudgment =
	include ?JudgmentSymbol 
	include ?JudgmentRules 
	include ?LFWithVariance 


theory PredSubSymbols =
	predsubtp #  V1T | 2  prec -10001 
  PredOf # PredOf 1 

  
theory PredSubRules =
  rule rules?Predsubtype 
  rule rules?Predsubrule 
  rule rules?PredsubTyping 
  rule rules?PredOfTerm 

  
theory LFPredSub =
	include ?PredSubSymbols 
	include ?PredSubRules 
	include ?LFWithVariance 

  
theory AllSubtypes =
	// include ?SubSymbol ❙
	// include ?SubRules ❙
	include ?JudgmentSymbol 
	include ?JudgmentRules 
	include ?PredSubSymbols 
	include ?PredSubRules 

  
theory LFSubtyped =
	include ?AllSubtypes 
	include ?LFWithVariance 

namespace http://gl.mathhub.info/MMT/LFX/TypedHierarchy 
import rules scala://TypedHierarchy.LFX.mmt.kwarc.info
import lf scala://lf.mmt.kwarc.info 

fixmeta http://cds.omdoc.org/mmt?mmt 

theory Symbols =
   TypeLevel # 𝒰 1 prec -1000 
   UnspecifiedTypeLevel # 𝒰 prec -999 


theory Rules =
	 rule rules?TypeLevelUniverse 
	 rule rules?TypeLevelSubRule 
	 rule rules?LevelType 


theory TypedHierarchy =
   include ☞http://cds.omdoc.org/urtheories?ModExp
   include ☞ur:?Typed 
   include ☞ur:?Kinded 
   include ☞ur:?NatLiteralsOnly 
   include ?Symbols 
   include ?Rules 
   rule rules?LevelComputation 


theory LFHierarchy =
   include ?TypedHierarchy 
   include ☞ur:?PLF 
   
   rule rules?PiHierarchy
   rule rules?LambdaHierarchy
   rule rules?Polymorphism
   rule rules?PolymorphismLambda 

namespace http://gl.mathhub.info/MMT/LFX/WTypes 
import rules scala://WTypes.LFX.mmt.kwarc.info

fixmeta http://cds.omdoc.org/mmt?mmt 

theory Symbols =
	wtype # W V1T . 2 prec -10000 
	sup # sup 2 , V1  3 to 4 prec -8000 
	rec # rec 4 , V1 , V2 , V3  5 to 6  prec -8000 

	
theory Rules =   
   rule rules?WTypeFormation 
   rule rules?SupIntroduction 
   rule rules?WEquality 
   rule rules?RecElimination 
   rule rules?RecComputation 
   // rule info.kwarc.mmt.LFX.WTypes.supEquality ❙

   

theory WTypes =
	include ☞ur:?LF 
	include ?Symbols 
	include ?Rules 

	
theory LFW =
	include ?WTypes 
	include ☞http://gl.mathhub.info/MMT/LFX/Finite?LFFinite 


theory Inductive =
	include ?LFW 
	include ☞http://gl.mathhub.info/MMT/LFX/Sigma?LFSigma 
	rule rules?InductiveTypes 
	rule rules?InductiveDefs 

namespace http://gl.mathhub.info/MMT/LFX/Quote-Eval 

fixmeta http://cds.omdoc.org/mmt?mmt 

theory Symbols =
	Construction #  
	quoteOp #  1  prec -1000 
	evalOp # |⌜ 1 ⌝| prec -1100 
	unquoteOp #  1  prec -1000 

namespace http://foswiki.cs.uu.nl/foswiki/IFIP21/Goteborg/MMT-tutorial-final

theory Types : ur:?LF =
  tp : type
  tm : tp ⟶ type # tm 1 prec -1


theory Logic : ur:?LF =
  prop: type
  ded : prop ⟶ type#  1 prec -1role Judgment


theory Equality : ur:?LF =
  include ?Types
  include ?Logic
  equal : {A} tm A ⟶ tm A ⟶ prop# 2 = 3
  refl : {A,X:tm A} ⊦ X = X
  sym : {A,X,Y:tm A} ⊦ X = Y ⟶ ⊦ Y = X
  trans : {A,X,Y,Z:tm A} ⊦ X = Y ⟶ ⊦ Y = Z ⟶ ⊦ X = Z
  cong  : {A,B,X,Y,F:tm A ⟶ tm B} ⊦ X = Y ⟶ ⊦ (F X) = (F Y)


theory STT : ur:?LF =
  include ?Equality
  
  fun : tp ⟶ tp ⟶ tp# 1  2
  abstract : {A,B} (tm A ⟶ tm B) ⟶ tm (A ⇒ B)# λ 3  
  apply : {A,B} tm (A ⇒ B) ⟶ tm A ⟶ tm B# 3 @ 4 prec 5
  
  beta : {A,B,F: tm A ⟶ tm B,X} ⊦ (λ F) @ X = (F X)


theory Eta : ur:?LF =
  include ?STT
  eta : {A,B,F: tm (A ⇒ B)} ⊦ (λ [x: tm A] (F @ x)) = F


theory Extensionality : ur:?LF =
  include ?STT
  ext : {A,B,F,G: tm (A ⇒ B)} ({x: tm A} ⊦ F @ x = G @ x) ⟶ ⊦ F = G# ext 5


//  view EtaExt : ?Eta -> ?Extensionality =
  // include mmtid ?STT❙
  eta = [A,B,F] ext [x] beta❙


theory List : ?STT =
  list : tp ⟶ tp# < 1 >
  nilOf : {A: tp} tm <A># nil %I1
  cons : {A: tp} tm A ⟶ tm <A> ⟶ tm <A># 2 + 3 prec 10
  
  fold : {A,B} tm B ⟶ (tm A ⟶ tm B ⟶ tm B) ⟶ tm <A> ⟶ tm B
  fold_nil : {A,B,N,C} ⊦ fold A B N C nil = N
  fold_cons : {A,B,N,C,X,L} ⊦ fold A B N C (X+L) = C X (fold A B N C L)
      
  map : {A,B} tm (A ⇒ B) ⟶ tm <A> ⟶ tm <B>= [A,B,f] fold A <B> nil ([a,bs] (f@a)+bs)# map 3 4
  append : {A} tm <A> ⟶ tm <A> ⇒ <A>= [A] fold A (<A> ⇒ <A>) (λ[x]x) ([a,f] λ[l]a+(f@l))
  flatten: {A} tm < <A> > ⟶ tm <A>= [A] fold <A> <A> nil ([l,r] (append A l) @ r)


theory Monad : ?STT =
  operator: tp ⟶ tp# M 1 prec 20
  unit : {A} tm A ⟶ tm M A# return 2
  bind : {A,B} tm M A ⟶ tm (A ⇒ M B) ⟶ tm M B# 3 > 4 prec 5
 
  neutral_left : {A,B,F: tm (A ⇒ M B)}{X: tm A} ⊦ (return X) > F = F @ X
  neutral_right : {A,m: tm M A} ⊦ m > (λ [x] return x) = m
  assoc: {A,B,C, F: tm (A ⇒ M B), G: tm (B ⇒ M C),m: tm M A} ⊦ (m > F) > G = m > (λ[x]F @ x > G) 


view ListMonad : ?Monad -> ?List = 
  operator = list
  unit = [A] [x] x+nil
  bind = [A,B][l,f] (flatten B) (map f l)

  // neutral_left = ...❙
  // neutral_right = ...❙
  // assoc = ...❙


theory MonadPlus : ?STT =
  include ?Monad
  // more stuff here❙

namespace http://cds.omdoc.org/examples/ijcar 

import rules scala://mmt.kwarc.info

theory Nat : ../urtheories?LF =
  nat : type
  zero: nat
  succ: nat⟶nat # 1 ' prec 10
  
  rule rules/lf?Realize nat  rules/api/uom?StandardNat
  rule rules/lf?Realize zero rules/api/uom?Arithmetic/Zero
  rule rules/lf?Realize succ rules/api/uom?Arithmetic/Succ


theory Bool : ../urtheories?LF =
  bool: type
  proof: bool ⟶ type #  1 prec -5


theory DHOL : ../urtheories?LF  =
  include ?Nat
  include ?Bool
  rule rules/lf?ShallowPolymorphism
  equal : {a:type} a ⟶ a ⟶ bool # 2 = 3 prec 5


theory Double : ?DHOL =
  double : nat ⟶ nat
  double_zero: ⊦ double 0 = 0
  double_succ: {x} ⊦ double(x') = (double x)''

namespace http://cds.omdoc.org/examples

theory TopologicalArgumentationTheory : http://cds.omdoc.org/urtheories?LF =
  include ?PL
  
  K : prop ⟶ prop
  B : prop ⟶ prop
  box: prop  ⟶ prop  #  1

  world : type
  
  argument: type
  attacks : argument ⟶ argument ⟶ type # 1  2
  
  in : world ⟶ argument ⟶ type # 1 ‍∈ 2
  holds : world ⟶ prop ⟶ type  # 1  2
  Fix : argument ⟶ type
  
  holds_conj : {w,F,G} w ⊧ F ⟶ w ⊧ G ⟶ w ⊧ F ∧ G
  holds_disj1 : {w,F,G} w ⊧ F ⟶ w ⊧ F ∨ G
  holds_disj2 : {w,F,G} w ⊧ G ⟶ w ⊧ F ∨ G
  
  holds_K : {w,F} ({v} v ⊧ F) ⟶ w ⊧ K F
  holds_box : {w,F,T} w ‍∈ T ⟶ ({v} v ‍∈ T ⟶ v ⊧ F) ⟶ w ⊧ □ F
  holds_B : {w,F,T} w ‍∈ T ⟶ Fix T ⟶ ({v} v ‍∈ T ⟶ v ⊧ F) ⟶ w ⊧ B F

namespace http://cds.omdoc.org/examples

//   An abstraction over the rational numbers and the arithmetic operations.❚

theory Numbers : http://cds.omdoc.org/urtheories?LF =
  sort : type 
  tm   : sort ⟶ type 
  
  prop  : type 
  equal : {S} tm S ⟶ tm S ⟶ prop      # 2 = 3  ## 2 = _ 1 3   role Eq
  forall : {S} (tm S ⟶ prop) ⟶ prop   #  V2T . -3 prec -10   ##  _ V2T -3 prec -10 

  ded   : prop ⟶ type   # ded 1 prec -1   role Judgment

  rat   : sort  
  tmrat : type   = tm rat  #  

  zero :  # _0  ## %D0
  succ : ℚ ⟶ ℚ  # 1 ' prec 170 
  one  :  # _1  = _0 ' ## %D1
  two  :  # _2  = _1 ' ## %D2

  add  : ℚ ⟶ ℚ ⟶ ℚ   # 1 + 2 prec 150 
  sub  : ℚ ⟶ ℚ ⟶ ℚ   # 1 - 2 prec 150 
  neg  : ℚ ⟶ ℚ       # - 1   prec 170 

  mult : ℚ ⟶ ℚ ⟶ ℚ   # 1 · 2 prec 155 
  div  : ℚ ⟶ ℚ ⟶ ℚ   # 1 / 2 prec 155 

  exp  : ℚ ⟶ ℚ ⟶ ℚ   # 1 ^ 2 prec 160 

  power_example : ded ∀x.∀y.∀z.x^(y+z)=x^y·x^z 


theory Rules : http://cds.omdoc.org/urtheories?LF =
  // Simplification rules for the rational numbers. ❙ 
  include ?Numbers
  
  // addition ❙
  add_zero_L : {x} ded _0 + x = x  role Simplify
  add_zero_R : {x} ded x + _0 = x  role Simplify
  add_succ_L : {x,y} ded x ' + y = (x+y)' role Simplify 
  add_succ_R : {x,y} ded x + y' = (x+y)' role Simplify

  // subtraction ❙ 
  sub_add : {x,y,z} ded x-(y+z) = x-y-z   role Simplify 
  sub_zero : {x} ded x - _0 = x   role Simplify 
  
  // negation  ❙ 
  neg_neg  : {x} ded -(-x) = x  role Simplify 
  neg_add  : {x,y} ded -(x+y) = -x + (-y)  role Simplify  
  neg_zero : ded - _0 = _0  role Simplify 
  
  // multiplication ❙
  mult_zero_L : {x} ded _0 · x = _0 role Simplify
  mult_zero_R : {x} ded x · _0 = _0 role Simplify
  mult_one_L  : {x} ded _1 · x = x role Simplify
  mult_one_R  : {x} ded x · _1 = x role Simplify
  mult_succ_L : {x,y} ded x'·y = x + x · yrole Simplify
  mult_succ_R : {x,y} ded x·y' = x·y+yrole Simplify
  mult_add_L  : {x,y,z} ded (x+y)·z = x·z+y·zrole Simplify
  mult_add_R  : {x,y,z} ded x·(y+z) = x·y+x·zrole Simplify
  mult_sub_L  : {x,y,z} ded (x-y)·z = x·y-y·zrole Simplify
  mult_sub_R  : {x,y,z} ded x·(y-z) = x·y-x·zrole Simplify
  mult_neg_L  : {x,y} ded (-x)·y = -(x·y)role Simplify
  mult_neg_R  : {x,y} ded x·(-y) = -(x·y)role Simplify
  
  // exponentiation ❙
  exp_zero : {x} ded x ^ _0 = _1 role Simplify
  exp_one  : {x} ded x ^ _1 = x role Simplify
  exp_add  : {x,y,z} ded x^(y+z) = x^y·x^z   role Simplify
  exp_exp  : {x,y,z} ded x^(y^z) = x^(y·z)   role Simplify
  one_exp  : {x} ded _1 ^ x = _1  role Simplify
  exp_mult : {x,y,z} ded (x·y)^z = x^z·y^z   role Simplify 


//   A sort of natural numbers and a big sum operator with notations for parsing and presentation.❚
theory Sums : http://cds.omdoc.org/urtheories?LF =
  include ?Numbers

  nat   : sort  
  tmnat : type  = tm nat  #   
  incl  : ℕ ⟶ ℚ  # $ 1 prec 170 ## 1 prec 100000000

  sum  : ℕ ⟶ ℕ ⟶ (ℕ ⟶ ℚ) ⟶ ℚ  
       # Σ 1 to 2 3  prec 155
      ## Σ __ 1 ^^ 2 3 prec 155
  sum_example   : ded ∀m.∀n. Σ m to n ([i]$i)=($m·($m+ _1)-$n·($n+ _1))/ _2 

namespace http://cds.omdoc.org/examples

/T regular bands and views between them
mostly following the wikipedia page on Bands

Notes: 
- some names that were not given on Wikipedia are made up
- most views do not actually use (all of) the Band properties
- LeftX and RightX are stronger than X, not weaker


theory Regular : ?FOLEQNatDed =
	include ?Band 
  regular: {x,y,z} ⊦ z∘x∘z∘y∘z ≐ z∘x∘y∘z 


theory LeftNormal : ?FOLEQNatDed =
	include ?Band 
  leftregular1: {x,y,z} ⊦ z∘x∘z∘y ≐ z∘x∘y 


theory LeftRegular : ?FOLEQNatDed =
	include ?Band 
  leftregular: {x,z} ⊦ z∘x∘z ≐ z∘x 


theory RightNormal : ?FOLEQNatDed =
	include ?Band 
  rightregular1: {x,y,z} ⊦ x∘z∘y∘z ≐ x∘y∘z 


theory RightRegular : ?FOLEQNatDed =
	include ?Band 
  rightregular: {y,z} ⊦ z∘y∘z ≐ y∘z 


/T views for the three stages of regular band theories ❚

implicit view Regular2LeftNormal : ?Regular -> ?LeftNormal =
  include ?Band
	regular = [x,y,z] congT leftregular1 [u]u∘z


implicit view LeftNormal2LeftRegular : ?LeftNormal -> ?LeftRegular =
  include ?Band
	leftregular1 = [x,y,z] congT leftregular [u]u∘y


implicit view Regular2RightNormal : ?Regular -> ?RightNormal =
  include ?Band
	regular = [x,y,z] trans3 assoc5 (congT (trans3 assoc4R rightregular1 assoc) [u]z∘u) assoc4R


implicit view RightNormal2RightRegular : ?RightNormal -> ?RightRegular =
  include ?Band
	rightregular1 = [x,y,z] trans3 assoc4 (congT (trans assocR rightregular) [u] x∘u) assocR


/T normal bands ❚

theory Normal : ?FOLEQNatDed =
	include ?Band 
  normal: {x,y,z} ⊦ z∘(x∘y)∘z ≐ z∘(y∘x)∘z 


theory RightCommutative : ?FOLEQNatDed =
	include ?Band 
  leftnormal: {x,y,z} ⊦ z∘(x∘y) ≐ z∘(y∘x) 


theory LeftCommutative : ?FOLEQNatDed =
	include ?Band 
  rightnormal: {x,y,z} ⊦ (x∘y)∘z ≐ (y∘x)∘z 


/T views for the diamond of normal band theories (with semilattices at the bottom) ❚

implicit view Normal2RightCommutative : ?Normal -> ?RightCommutative =
  include ?Band
	normal = [x,y,z] congT leftnormal [u]u∘z


implicit view Normal2LeftCommutative : ?Normal -> ?LeftCommutative =
  include ?Band
	normal = [x,y,z] trans3 assoc (congT rightnormal [u]z∘u) assocR


view RightCommutative2Semilattice : ?RightCommutative -> ?Semilattice =
  include ?Band
	leftnormal = [x,y,z] congT comm [u]z∘u


implicit view LeftCommutative2Semilattice : ?LeftCommutative -> ?Semilattice =
  include ?Band
	rightnormal = [x,y,z] congT comm [u]u∘z


/T views from regular to normal band theories ❚

implicit view LeftNormal2Normal : ?LeftNormal -> ?Normal =
  include ?Band
  // zxzy = zxzyzxzy = zx yz zxzy = zxy zx zy = zxy xz zy = zxy zxy = zxy❙
  leftregular1 = [x,y,z] trans3 (sym idempotent) _ idempotent


implicit view LeftRegular2RightCommutative : ?LeftRegular -> ?RightCommutative =
  include ?Band
	leftregular = [x,z] trans4 assoc leftnormal assocR (congT idempotent [u]u∘x)


implicit view RightNormal2Normal : ?RightNormal -> ?Normal =
  include ?Band
  // xzyz = xzyz xzyz = x yz zxzyz = xy zxzyz = xyz zx yz = xyz xyz = xyz❙
	rightregular1 = [x,y,z] trans3 (sym idempotent) _ idempotent


implicit view RightRegular2LeftCommutative : ?RightRegular -> ?LeftCommutative =
  include ?Band
	rightregular = [y,z] trans3 rightnormal assoc (congT idempotent [u]y∘u)


/T rectangular bands (the axioms here already imply idempotency)❚

theory Rectangular : ?FOLEQNatDed =
	include ?Band 
  rectangular: {x,y} ⊦ x∘y∘x ≐ x 
  
  // provable ❙
  rectangularAny: {x,y,z} ⊦ x∘y∘z ≐ x∘z


theory LeftZero : ?FOLEQNatDed =
	include ?Band 
  leftsingular: {x,y} ⊦ x∘y ≐ x 


theory RightZero : ?FOLEQNatDed =
	include ?Band 
  rightsingular: {x,y} ⊦ x∘y ≐ y 

namespace http://cds.omdoc.org/examples

//   binary arithmetic ❚
theory Binary : http://cds.omdoc.org/urtheories?LF =
  num  : type
  // the number 0❙
  zero : num # b
  // double, i.e., append the digit 0❙
  db: num ⟶ num # 1  prec 10
  // double and increment, i.e., append the digit 1❙
  dbI: num ⟶ num # 1  prec 10
  
  equal : num ⟶ num ⟶ type# 1 = 2 prec 0 role Eq
  refl  : {n} n = n# refl %I1
  
  // successor and its rules❙
  succ: num ⟶ num# 1 ' prec 5
  succ_zero:      b ' = b ₁  role Simplify
  succ_db:  {n} n ₀ ' = n ₁  role Simplify
  succ_dbI: {n} n ₁ ' = n'₀ role Simplify

  test : b₁₁' = b₁₀₀ = refl
  
  // addition and its rules❙
  plus: num ⟶ num ⟶ num# 1 + 2 prec 3
  plus_zero_right: {n} n + b = n                role Simplify
  plus_zero_left:  {n} b + n = n                role Simplify
  // these rules cannot be picked up by the SimplificationRuleGenerator yet❙
  plus_db_db:    {m,n} m ₀ + n ₀ = (m + n) ₀    // role Simplify
  plus_db_dbI:   {m,n} m ₀ + n ₁ = (m + n) ₁    // role Simplify
  plus_dbI_db:   {m,n} m ₁ + n ₀ = (m + n) ₁    // role Simplify
  plus_dbI_dbI:  {m,n} m ₁ + n ₁ = ((m + n) ')₀ // role Simplify

namespace http://cds.omdoc.org/examples/epa

fixmeta ur:?LF

// --------------------------- base languages --------------------------- ❚

theory Propositions =
  prop  : type


theory Proofs =
  include ?Propositions
  ded   : prop ⟶ type#  1  prec -5


theory Logic =
  include ?Propositions
  include ?Proofs


theory Terms =
  term : type


theory Types =
  tp: type


theory TypedTerms =
  include ?Types
  tm: tp ⟶ type# tm 1 prec -5


theory SoftTypedTerms =
  include ?Terms
  include ?Types
  include ?Propositions
  of : term ⟶ tp ⟶ prop# 1  2 prec 30


theory Kinds =
  kd : type


theory KindedTypes =
  include ?Kinds
  tf : kd ⟶ type# tf 1 prec -5
  tpk : kd


theory UntypedLogic =
  include ?Logic
  include ?Terms


theory TypedLogic =
  include ?Logic
  include ?TypedTerms


theory SoftTypedLogic =
  include ?SoftTypedTerms
  include ?Logic
         

theory InternalPropositions =
  include ?TypedTerms
  bool: tp

  realize ?Propositions
  prop = tm bool

  include ?Proofs


theory InternalTypes =
  include ?UntypedLogic
  in : term ⟶ term ⟶ prop# 1  2 prec 30

  total structure typesAsObjects : ?SoftTypedTerms =
    include ?Terms
    include ?Propositions
    tp = term
    of = in
  
  
  total structure typesAsPredicates : ?SoftTypedTerms =
    include ?Terms
    include ?Propositions
    tp = term ⟶ prop
    of = [X,A] A X
  


// --------------------------- equality --------------------------- ❚

theory Equality =
  include ?UntypedLogic
  equal : term ⟶ term ⟶ prop# 1  2 prec 30

  refl  : {x} ⊦ x ≐ x
  congP : {x,y} ⊦ x ≐ y ⟶ {P: term ⟶ prop} ⊦ P x ⟶ ⊦ P y


theory SoftTypedEquality =
  include ?SoftTypedLogic
  include ?Equality


theory TypedEquality =
  include ?TypedLogic
  equal  : {A} tm A ⟶ tm A ⟶ prop# 2  3 prec 30

  refl   : {A,x: tm A} ⊦ x ≐ x   # refl %I2
  congP  : {A,  x,y} ⊦ x ≐ y ⟶ {P: tm A ⟶ prop} ⊦ P x ⟶ ⊦ P y# 4 congP 5 6

  congT  : {A,B,x,y} ⊦ x ≐ y ⟶ {T: tm A ⟶ tm B} ⊦ T x  ≐  T y # 5 congT 6
         = [A,B,x,y,p,T] p congP ([u] T x ≐ T u) refl
  
  sym    : {A, x,y: tm A} ⊦ x ≐ y ⟶ ⊦ y ≐ x# 4 sym
         = [A,x,y,p] p congP ([u]u≐x) refl
  trans  : {A, x,y,z: tm A} ⊦ x ≐ y ⟶ ⊦ y ≐ z ⟶ ⊦ x ≐ z# 5 trans 6
         = [A,x,y,z,p,q] q congP ([u]x≐u) p


// --------------------------- function types --------------------------- ❚

theory SimpleFunctionTypes =
  include ?Types
  simpfun : tp ⟶ tp ⟶ tp# 1 %R→ 2 prec 50


theory SimpleFunctions =
  include ?SimpleFunctionTypes
  include ?TypedEquality

  simplambda: {A,B} (tm A ⟶ tm B) ⟶ tm A → B# λ 3 prec 40
  simpapply: {A,B} tm A → B ⟶ tm A ⟶ tm B# 3 @ 4 prec 50
  simpbeta : {A,B,F: tm A ⟶ tm B, X} ⊦ (λ F) @ X ≐ F X


theory DependentFunctionTypes =
  include ?TypedTerms
  depfun : {A} (tm A ⟶ tp) ⟶ tp# Π 2 prec 40

  realize ?SimpleFunctionTypes
  simpfun = [A,B] Π [x: tm A] B


theory DependentFunctions =
  include ?DependentFunctionTypes
  include ?TypedEquality
  deplambda: {A,B} ({x: tm A} tm B x) ⟶ tm Π B# λ 3 prec 40
  depapply: {A,B} tm Π B ⟶ {x: tm A} tm B x # 3 @ 4 prec 50
  depbeta : {A,B,F:{x:tm A} tm B x, X} ⊦ (λ F) @ X ≐ F X


theory SoftTypedFunctions =
  include ?Terms
  include ?SoftTypedEquality
  lambda: (term ⟶ term) ⟶ term# λ 1 prec 40
  apply : term ⟶ term ⟶ term# 1 @ 2 prec 50
  beta  : {F,X} ⊦ (λ F) @ X ≐ F X


theory SoftTypedSimpleFunctions =
  include ?SoftTypedTerms
  include ?SoftTypedFunctions
  include ?SimpleFunctionTypes

  fun_typing : {A,B,F} ({x} ⊦ x⦂A ⟶ ⊦ (F x)⦂B) ⟶ ⊦ λ F ⦂ A → B


theory SoftDependentFunctionTypes =
  include ?SoftTypedTerms
  softfun : tp ⟶ (term ⟶ tp) ⟶ tp# Π 1 2 prec 40


theory SoftTypedDependentFunctions =
  include ?SoftTypedTerms
  include ?SoftTypedFunctions
  include ?SoftDependentFunctionTypes
  
  fun_typing : {A,B,F} ({x} ⊦ x⦂A ⟶ ⊦ (F x)⦂(B x)) ⟶ ⊦ λ F ⦂ Π A B


theory SimpleFunctionsEta =
  include ?SimpleFunctions
  eta: {A,B,F:tm A → B} ⊦ (λ[x] F @ x) ≐ F


theory SimpleFunctionsExtensionality =
  include ?SimpleFunctions
  exten: {A,B,F,G:tm A → B} ({x} ⊦ F@x ≐ G@x) ⟶ ⊦ F≐G

namespace http://cds.omdoc.org/examples

//   A representation of homotopy type theory (HOTT) in MMT instantiated with LF-modulo.
     This is a Martin-Löf-style type theory with the univalence axiom.
     Simplification rules are used to offset artefacts produced by the representation.
     The representation follows the HOTT book (The Univalent Foundations Program, Institute for Advanced Study, Princeton, April 2013).❚

theory HOTT : http://cds.omdoc.org/urtheories?LF =
  // The levels of the universe hierarchy (essentially the natural numbers). ❙
  level : type 
  first : level 
  next  : level ⟶ level 
  
  // The syntactic categories: LF-types for the HOTT types and terms at each level. ❙
  
  // tp L represents the types at level L. ❙
  tp    : level ⟶ type 
  // univ L is the universe containing the types at level L. ❙
  univ  : {L} tp (next L) 
  // if A:tp L, then tm A represents the terms of type A ❙
  tm    : {L} tp L ⟶ type  # tm 2 prec -5

  // Equality judgments for types (at the same level) and terms (of the same type).
     These are registered as equality judgements by "role Eq", which permits registering equality rules later. ❙
  
  tp_equal : {L} tp L ⟶ tp L ⟶ type                   role Eq
  equal : {L, A:tp L} tm A ⟶ tm A ⟶ type  # 3  4   role Eq

  // The above encoding is not quite adequate
     (a) the cumulativity of the type hierarchy is not represented
     (b) the fact that every type at level L is also a term of type univ L is not captured. ❙
  
  // Up and up take care of (a): they move types and terms up in the hierarchy. ❙ 
  Up      : {L} tp L ⟶ tp (next L)  # Up 2
  up      : {L,A:tp L} tm A ⟶ tm (Up A)  # up 3

  // shift and unshift take care of (b): they convert between types and terms. ❙
  shift   : {L} tp L ⟶ tm (univ L)  # shift 2
  unshift : {L} tm (univ L) ⟶ tp L  # unshift 2
  
  // Two equality axioms that make shift and unshift bijections.
     By registering them as simplification rules, the type checker becomes aware of the bijection. ❙
  shift_unshift : {L,A: tp L} tp_equal L (unshift (shift A)) A   role Simplify
  unshift_shift : {L,A: tm univ L} (shift (unshift A)) ≡ A       role Simplify
  
  // The usual rules for equality. Some rules are omitted (congruence and equality of types) ❙
  refl  : {L, A:tp L, X:tm A} X ≡ X                              # %%prefix 2 1
  sym   : {L, A:tp L, X:tm A, Y: tm A} X ≡ Y ⟶ Y ≡ X             # %%prefix 4 1
  trans : {L, A:tp L, X:tm A, Y: tm A, Z: tm A} X ≡ Y ⟶ Y ≡ Z ⟶ X ≡ Z   # %%prefix 5 2

  // The development of HOTT type theory is now straightforward.
     The following follows A.2 in the HOTT book.
     Only the constructors and rules needed to state the univalence axiom are given.❙
  
  Pi     : {L, A:tp L} (tm A ⟶ tp L) ⟶ tp L                                  # Π 3 
  lambda : {L, A:tp L, B: tm A ⟶ tp L} ({x:tm A} tm (B x)) ⟶ tm Π [x] B x    # λ 4 
  apply  : {L, A:tp L, B: tm A ⟶ tp L} tm (Π [x: tm A] B x) ⟶ {x} tm (B x)   # 4 @ 5 prec 10 
  arrow  : {L} tp L ⟶ tp L ⟶ tp L 
         = [L,A,B] Π [x: tm A] B   
         # 2  3 prec 3
  id     : {L, A: tp L} tm A ⇒ A   
         = [L,A] λ [x] x  
         # id 2 prec 10
  comp   : {L, A: tp L, B: tp L, C: tp L} tm A ⇒ B ⟶ tm B ⇒ C ⟶ tm A ⇒ C  
         = [L,A,B,C] [f,g] λ [x:tm A] g @ (f @ x)  
         # 6  5 prec 10
  // Registering beta as a simplification rule has the effect that computation in HOTT is automated by MMT. ❙
  beta   : {L, A: tp L, B: tm A ⟶ tp L, F: {x: tm A} tm (B x), X: tm A} (λ F) @ X ≡ (F X) 
         # %%prefix 5 0   role Simplify
  eta    : {L, A:tp L, B: tm A ⟶ tp L, F: tm (Π [x: tm A] B x)} F ≡ λ [x: tm A] F @ x  
         # %%prefix 4 0
         
  Sigma  : {L, A:tp L} (tm A ⟶ tp L) ⟶ tp L                                     # Σ 3 
  pair   : {L, A:tp L, B: tm A ⟶ tp L} {x:tm A} tm (B x) ⟶ tm Σ [x] B x         # pair 4 5
  pi1    : {L, A:tp L, B: tm A ⟶ tp L} tm (Σ [x: tm A] B x) ⟶ tm A              # pi1 4 
  pi2    : {L, A:tp L, B: tm A ⟶ tp L} {u:tm (Σ [x: tm A] B x)} tm (B (pi1 u))  # pi2 4 
  prod   : {L} tp L ⟶ tp L ⟶ tp L 
         = [L,A,B] Σ [x: tm A] B   
         # 2 × 3 prec 3
  conv_pair : {L, A: tp L, B: tm A ⟶ tp L, u: tm Σ [x] B x} u ≡ pair (pi1 u) (pi2 u) 
            # %%prefix 4 0
  // conv_pi1 and conv_pi2 are registered as simplification rules in the same way as beta. ❙
  conv_pi1  : {L, A: tp L, B: tm A ⟶ tp L, X: tm A, Y: tm (B X)} pi1 (pair L A B X Y) ≡ X  
            //  We have to give the implicit arguments of pair here to aid type reconstruction. 
                (A better solution might be Twelf's abstraction behavior that adds the {B} binder.)
            # %%prefix 5 0  role Simplify 
  // Note that conv_pi2 only type-checks because conv_pi1 is used as a simplification rule. ❙  
  conv_pi2  : {L, A: tp L, B: tm A ⟶ tp L, X: tm A, Y: tm (B X)} pi2 (pair L A B X Y) ≡ Y  
            # %%prefix 5 0  role Simplify

  // We omit the type constructors +, empty, unit, and nat. ❙
  
  ident  : {L, A:tp L} tm A ⟶ tm A ⟶ tp L   # 3 = 4 prec 7
  idrefl : {L, A:tp L, x:tm A, y: tm A} x ≡ y ⟶ tm x = y   # idrefl 5  
         // The assumption x ≡ y is omitted in the HOTT book - derivable from congruence?
  idelim : {L, A: tp L}
           {C: {x: tm A, y: tm A, p: tm x = y} tp L}
           {c: {z: tm A} tm (C z z (idrefl (refl z)))}
           {a: tm A} {b: tm A} {p: tm a = b}
           tm (C a b p) 
         # idelim 3 4 5 6 7 
  idcomp : {L, A: tp L}
           {C: {x: tm A, y: tm A, p: tm x = y} tp L} 
           {c: {z: tm A} tm (C z z (idrefl (refl z)))}
           {a: tm A}
           tm (idelim C c a a (idrefl (refl a))) = (c a) 

  // An abbreviation for the identity type of two types (which requires converting the types to terms first). ❙
  tident : {L, A:tp L, B: tp L} tp (next L)   
         = [L,A,B] (shift A) = (shift B) 
         # 2 == 3 prec 5

  // Now the definitions of homotopy that lead to the univalence axiom. ❙
         
  // Definition 2.4.1 ❙
  homotopy    : {L, A: tp L, B} tm A ⇒ B ⟶ tm A ⇒ B ⟶ tp L 
              = [L,A,B,f,g] Π [x: tm A] f @ x = g @ x  
              # 4  5 prec 5
              
  // 2.4.10❙
  isequiv     : {L, A: tp L, B: tp L} tm A ⇒ B ⟶ tp L 
              = [L,A,B,f] (Σ [g: tm B ⇒ A] f ∘ g ∼ id B) × (Σ [h: tm B ⇒ A] h ∘ f ∼ id A) 
              # isequiv 4
              
  // 2.4.11❙
  equivalence : {L} tp L ⟶ tp L ⟶ tp L   
              = [L,A,B] Σ [f: tm A ⇒ B] isequiv f   
              # 2  3 prec 5

  // We will need the reflexivity of homotopy below. ❙
  // Note that without beta as a simplification rule, this proof would have to use a complex subterm
     instead of (refl x).❙
  ≃_refl_aux  : {L, A: tp L} tm (id A) ∘ (id A) ∼ (id A)  
              = [L,A] λ [x: tm A] idrefl (refl x)
  ≃_refl      : {L, A: tp L} tm A ≃ A   
              = [L,A] pair (id A) (pair  
                   (pair (id A) (≃_refl_aux L A))
                   (pair (id A) (≃_refl_aux L A))
                 )

  // Lemma 2.10.1 ❙
  // This only type-checks because unshift_shift is used as a simplification rule. ❙
  idtoeqv     : {L, A: tp L, B: tp L} tm A == B ⇒ (Up (A ≃ B)) 
              = [L,A,B] λ [P] idelim
                  ([a: tm univ L, b: tm univ L, p: tm a = b] Up ((unshift a) ≃ (unshift b)))
                  ([z: tm univ L] up (≃_refl L (unshift z)))
                  (shift A) (shift B) P
                  

  // Axiom 2.10.3 (univalence) ❙
  // Intuitively, this says (A == B) ≃ (A ≃ B) ❙
  univalence  : {L,A: tp L, B} tm (isequiv (idtoeqv L A B)) 
  
  // This is a consequence of univalence; proof to be added. ❙
  ≃_cong      : {L, M, P: tp L ⟶ tp M, A: tp L, B: tp L} tm (A ≃ B) ⟶ tm ((P A) ≃ (P B)) 

namespace http://cds.omdoc.org/examples 

import lfx http://gl.mathhub.info/MMT/LFX/TypedHierarchy 
import finite http://gl.mathhub.info/MMT/LFX/Finite 
import rules scala://structuralfeatures.lf.mmt.kwarc.info

theory InductivelyDefinedTypes : ?LFXI =
	include ?NatExample 
		
	theory list_decls > a : type ❘ =
		list: type 
    nil: list 
    cons: a ⟶ list ⟶ list 
  

	reflect list1(a: type) : ☞?InductivelyDefinedTypes/list_decls(a:type) 

  inductive list1_unreflected(a: type)  =
    list: type 
    nil: list 
    cons: a ⟶ list ⟶ list 
  
	
	inductive_definition concat(a:type) : list1(a: type)  =
		list : type  = list1/list a⟶ list1/list a 
		nil : list  = [l] l 
		cons : {x: a, f: list, l: list1/list a} list1/list a  = [x, f, l] (list1/cons a x (f l)) 
	

	single: {a : type} a ⟶ list1/list a  = [a, x] list1/cons a x (list1/nil a) 
	inductive_definition reverse(a: type) : list1(a:type)  =
		list : type  = list1/list a
		nil : list  = list1/nil a
		cons : {x: a, xs: list} list  = [x, xs] concat/list a xs (single a x) 
	

	inductive_definition length(a: type) : list1(a:type)  =
		list: type  = nats/n 
		nil: list  = nats/z 
		cons: {x: a, l:list} list  = [x, l] nats/s l 
	

// length: {a : type} list1/list a ⟶ nat/n ❘ = [a, l] (list1/induct/list a ([tp:type] nat/n) ([tp:type] nat/z) ([tp:type, x:tp, xs:nat/n] nat/s xs)) l ❙

	record pair(A: type, B: type)  = 
		a: A 
		b: B 
	
	product_type: type ⟶ type ⟶ type  # 1 * 2 prec 10  = [a, b] pair/Type a b 
	record_term pairs(A: type, B: type, x: A, y: B) : pair(A, B)  = 
		a: A  = x 
		b: B  = y 
	
	pair_term: {a: type, b: type} a ⟶ b ⟶ a * b  = [a, b, x, y] pairs/Make a b x y 

	inductive vector(a: type)  =
		vec: {n: nat/n} type 
		empty: vec nat/z 
		add: {n: nat/n} vec n ⟶ a ⟶ vec (nat/s n) 
	

	// ind_vec: {a: type, vecP: {a:type}{n: nat/n} type, emptyP: {a: type} (vecP a) nat/z, addP: {a: type}{n: nat/n}(vecP a) n ⟶ (a ⟶ (vecP a) (nat/s n)), n: nat/n} (vector/vec a) n ⟶ (vecP a) n ❘ = [a, vecP, emptyP, addP, n, l] ([ys] (vector/induct/vec a vecP emptyP addP n l) ys) ❙
	inductive_definition zip(a: type, b: type) : vector(a)  =
		vec: {n: nat/n} type  = [n] vector/vec b n  ⟶ vector/vec (a*b) n 
		empty: vec nat/z  = [l] vector/empty (a*b) 
		add: {n: nat/n} vec n ⟶ a ⟶ vec (nat/s n)  = [n, xs, x] vector/induct/vec b ([t, p] vector/vec (a*t) p) ([t] vector/empty (a*t)) ([t, p, ys, y] vector/add (a*t) p ys (pair_term a t x y)) (nat/s n) 
	

	inductive list2()  =
		list: type ⟶ type 
		nil: {a: type} list a 
		cons: {a: type} a ⟶ list a ⟶ list a 
		length2: {a:type} list a ⟶ nat/n 
		length2_nil: {a: type} DED (length2 a (nil a) EQ nat/z) 
		length2_cons: {a:type, hd: a, tl: list a} DED length2 a (cons a hd tl) EQ nat/s (length2 a tl) 
	
	
	inductive list3(a : type)  =
		list: type 
		nil: list 
		cons: {hd: a, tl:list} list   # 1  2 
		head: {l:list, P:DED (l NEQ nil)} a 
		head_cons: {hd: a, tl: list, P: DED (cons hd tl NEQ nil)} DED ((head (cons hd tl) P) EQ hd) 
	

	cons_nonempty: {a:type, hd:a, tl:list3/list a} DED (hd ∷ tl) NEQ list3/nil a  = [a, hd, tl] list3/no_conf_cons_nil a hd tl 
	// seems to be an universe issue
	head_cons: {a : type, hd: a, tl:list3/list a} DED (list3/head a (list3/cons a hd tl) (list3/no_conf_cons_nil a hd tl)) EQ hd ❘ = [a, hd, tl] list3/head_cons a hd tl (list3/no_conf_cons_nil a hd tl) ❙

	inductive FM(a: type)  =
		fm: type 
		gen: a ⟶ fm 
		unit: fm 
		comp: fm ⟶ fm ⟶ fm  # 1 . 2 
		assoc: {x: fm, y: fm, z: fm} DED comp (comp x y) z EQ comp x (comp y z) 
		unit_r: {x: fm} DED comp x unit EQ x 
		unit_l: {x: fm} DED comp unit x EQ x 
	

namespace http://cds.omdoc.org/examples 

import lfx http://gl.mathhub.info/MMT/LFX/TypedHierarchy 
import finite http://gl.mathhub.info/MMT/LFX/Finite 
import rules scala://structuralfeatures.lf.mmt.kwarc.info

theory Hofstadter : ?InductivelyDefinedTypes =
	inductive hofstadter()  =
		F: type 
		M: type 
		f: nat/n ⟶ F 
		m: nat/n ⟶ M 
		fToNat: F ⟶ nat/n 
		mToNat: M ⟶ nat/n 
  

	minus: nat/n ⟶ nat/n ⟶ nat/n  # 1 - 2 
	/T A nice example demonstrating why this feature doesn't allow for mutually inductive definitions over a (non-mutually) inductively-defined type 
		 This shouldn't be (and isn't) accepted by the feature, as the definition f_h refers to hofstadter/f (self or forward-reverences) are not (and can't be) expanded ❙
  // inductive_definition hofstadter_mf_sequences() : hofstadter() ❘ =
	// 	F: type ❘ = nat/n  ❙
	// 	M: type ❘ = nat/n  ❙
	// 	fToNat: nat/n ⟶ nat/n ❘ = [u] u ❙
	// 	mToNat: nat/n ⟶ nat/n ❘ = [u] u ❙
	// 	f_h: nat/n ⟶ nat/n*nat/n ❘ = [u] (nat/induct/n (nat/n * nat/n) (pair_term nat/n nat/n (nat/s nat/z) (nat/s nat/z)) ([x] 
	// 		(pair_term nat/n nat/n (pair/a nat/n nat/n x) ((nat/s (pair/a nat/n nat/n x)) - (hofstadter/mToNat (hofstadter/m (pair/b nat/n nat/n x))))))) u ❙
	// 	f: nat/n ⟶ nat/n ❘ = [u] (nat/induct/n nat/n (nat/s nat/z) ([v] (pair/b nat/n nat/n (f_h v)))) u ❙
 	// 	m_h: nat/n ⟶ nat/n*nat/n ❘ = [u] (nat/induct/n (nat/n * nat/n) (pair_term nat/n nat/n nat/z nat/z) ([x] 
	// 		(pair_term nat/n nat/n (pair/a nat/n nat/n x) ((nat/s (pair/a nat/n nat/n x)) - (f (pair/b nat/n nat/n x)))))) u ❙
	// 	m: nat/n ⟶ nat/n ❘ = [u] (nat/induct/n nat/n nat/z ([v] (pair/b nat/n nat/n (m_h v)))) u ❙
  // ❚

namespace http://cds.omdoc.org/examples 

import lfx http://gl.mathhub.info/MMT/LFX/TypedHierarchy 
import finite http://gl.mathhub.info/MMT/LFX/Finite 
import rules scala://structuralfeatures.lf.mmt.kwarc.info
import ur http://cds.omdoc.org/urtheories 

rule scala://parser.api.mmt.kwarc.info?MMTURILexer

theory LFXI = 
  include ☞ur:?DHOL
  include ☞lfx:?LFHierarchy
  rule rules?InductiveTypes
  rule rules?InductiveDefinitions
  rule rules?InductiveMatch
  rule rules?InductiveProofDefinitions
  rule rules?Reflections

  rule rules?Records
  rule rules?RecordDefinitions

namespace http://cds.omdoc.org/examples 

import lfx http://gl.mathhub.info/MMT/LFX/TypedHierarchy 
import finite http://gl.mathhub.info/MMT/LFX/Finite 
import rules scala://structuralfeatures.lf.mmt.kwarc.info
import ur http://cds.omdoc.org/urtheories 


theory NatManually : ur:?DHOL =
  n: type
  z : n
  s : n ⟶ n
  induct_n : {N:type,Z:N,S:N⟶N} n ⟶ N 
  induct_z : {N:type,Z:N,S:N⟶N} DED (induct_n N Z S) z EQ Z 
  induct_s : {N:type,Z:N,S:N⟶N,X:n} DED (induct_n N Z S) (s X) EQ S ((induct_n N Z S) X)  # induct_s 4 
  
  p_n: type  = n ⟶ n 
  p_z: p_n  = [x] x 
  p_s: p_n ⟶ p_n  = [f][x] s (f x) 
  
  p_induct_n: n ⟶ p_n  = induct_n p_n p_z p_s 
  p_induct_z: DED (induct_n p_n p_z p_s z) EQ p_z  = induct_z 
  p_induct_s: {X:n} DED (induct_n p_n p_z p_s (s X)) EQ p_s (induct_n p_n p_z p_s X) 
            = [X] induct_s X 
  
  N_n : n ⟶ type = [x] DED p_induct_n x z EQ x 
  N_z : N_n z = p_induct_z CONG [f:p_n] f z 
  N_s : {X:n,hX: N_n X} N_n (s X) 
      = [X:n][hX:N_n X] ((induct_s X) CONG [f] f z) TRANS (hX CONG s) 


theory NatExample : ?LFXI =
	theory nat_decls_long = 
		n: type 
    z: n 
    s: n ⟶ n 
  

	reflect nat_long() : NatExample/nat_decls_long() 
  inductive_definition plusn_long() : nat_long()  =
		n = nat_long/n ⟶ nat_long/n 
		z: n  = ([x] x) 
		s: n ⟶ n  = ([u,x] nat_long/s (u x)) 
  


	theory unital_type =
		n: type 
    z: n 
  

	theory nat_decls = 
		include ?NatExample/unital_type 
    s: n ⟶ n 
  
	reflect nat() : NatExample/nat_decls() 


  inductive_definition plusn() : nat()  =
		n = nat/n ⟶ nat/n 
		z: n  = ([x] x) 
		s: n ⟶ n  = ([u,x] nat/s (u x)) 
  
	plus: nat/n ⟶ nat/n ⟶ nat/n  = plusn/n  # 1 + 2 prec 100 

	ind_proof z_left_neutral() : nat() =
		n = [m] DED (nat/z + m) EQ m 
		z = plusn/z/Applied nat/z 
		s : {x:nat/n} n x ⟶ n (nat/s x)  = [x, px] plusn/z/Applied (nat/s x) 
  

	ind_proof z_right_neutral() : nat() =
		n = [m] DED m EQ (m + nat/z) 
		z = SYM (plusn/z/Applied nat/z) 
		s : {x:nat/n} n x ⟶ n (nat/s x)  = [x, px] (px CONG nat/s) TRANS (SYM (plusn/s/Applied x nat/z)) 
  

	ind_proof suc_comm() : nat() =
	 	n = [a:nat/n, b:nat/n] DED (nat/s a) + b EQ a + (nat/s b) 
	 	z : {b:nat/n} n nat/z b  = [b] ((plusn/s/Applied nat/z b) TRANS ((plusn/z/Applied b) CONG nat/s)) TRANS (SYM (plusn/z/Applied (nat/s b))) 
	 	s : {a:nat/n, b: nat/n} n a b ⟶ n (nat/s a) b  = [a: nat/n, b: nat/n, pa: n a b] ((plusn/s/Applied (nat/s a) b) TRANS (pa CONG nat/s)) TRANS (SYM (plusn/s/Applied a (nat/s b))) 
  

	ind_proof plus_comm() : nat()  =
		n = [a:nat/n, b:nat/n] DED a + b EQ b + a 
		z : {b: nat/n} n nat/z b  = [b] (z_left_neutral/n b) TRANS (z_right_neutral/n b) 
		s : {a:nat/n, b: nat/n, pa: n a b} n (nat/s a) b  = [a, b, pa] ((plusn/s/Applied a b) TRANS (pa CONG nat/s))
			 TRANS ((SYM (plusn/s/Applied b a)) TRANS (suc_comm/n b a))  
	

	ind_proof plus_assoc() : nat()  =
		n : {b:nat/n, a:nat/n, c:nat/n} type  = [b, a, c] DED a + (b + c) EQ (a + b) + c 
		z : {a, c} n nat/z a c  = [a, c]  (z_left_neutral/n c CONG ([x] a + x)) TRANS (z_right_neutral/n a CONG ([x] x + c)) 
		s : {b, a, c, pb: n b a c} n (nat/s b) a c  = [b, a, c, pb] ((((plusn/s/Applied b c) CONG ([x] a + x)) TRANS (SYM (suc_comm/n a (b+c)))) TRANS (plusn/s/Applied a (b+c)))
			TRANS ((pb CONG nat/s) TRANS (SYM ((((SYM (suc_comm/n a b)) TRANS (plusn/s/Applied a b)) CONG ([x] x + c)) TRANS (plusn/s/Applied (a+b) c)))) 
	

	inductive_definition times() : nat() =
		n: type  = (nat/n ⟶ nat/n) 
    z: n  = ([x] nat/z) 
    s: n ⟶ n  = ([u,x] (x + (u x))) 
  

	timesn: nat/n ⟶ nat/n ⟶ nat/n  = [a, b] times/n a b  # 1 * 2 prec 101  
	
	ind_proof times_z() : nat()  =
		n : {a:nat/n} type  = [a] DED a * nat/z EQ nat/z 
		z : n nat/z  = times/z/Applied nat/z 
		s : {a:nat/n, pa: n a} n (nat/s a)  = [a, pa] (times/s/Applied a nat/z) TRANS (plusn/z/Applied (a * nat/z)) TRANS pa  
	
	
	ind_proof times_right() : nat()  =
		n : {b:nat/n, a:nat/n} type  = [b, a] DED b + b * a EQ b * (nat/s a) 
		z : {a: nat/n} n nat/z a  = [a] ((plusn/z/Applied (nat/z * a)) TRANS (times/z/Applied a)) TRANS SYM (times/z/Applied (nat/s a)) 
		s : {b:nat/n, a:nat/n, pb: n b a} n (nat/s b) a  = [b, a, pb] 
						(((plusn/s/Applied b ((nat/s b)*a)) TRANS ((times/s/Applied b a) CONG ([x] nat/s (b + x))))
			TRANS (((plus_assoc/n a b (b*a)) CONG nat/s) TRANS ((plus_comm/n b a) CONG ([x] nat/s (x + (b*a))))))
			TRANS (((SYM (plusn/s/Applied (a+b) (b*a))) TRANS ((SYM (plusn/s/Applied a b)) CONG ([x] x + (b*a))))
			TRANS ((SYM (plus_assoc/n b (nat/s a) (b*a))) TRANS ((pb  CONG ([x] (nat/s a) + x)) TRANS (SYM (times/s/Applied b (nat/s a))))))  
	

	ind_proof distrib_left() : nat()  =
		n : {a:nat/n, b:nat/n, c:nat/n} type  = [a, b, c] DED (a + b) * c EQ a*c + b*c 
		z : {b:nat/n, c:nat/n} n nat/z b c  = [b, c] ((plusn/z/Applied b) CONG ([x] x * c)) TRANS (SYM ((times/z/Applied c) CONG ([x] x+ (b*c)) TRANS (plusn/z/Applied (b*c)))) 
		s = [a, b, c, pa] ((((plusn/s/Applied a b) CONG ([x] x * c)) TRANS (times/s/Applied (a+b) c)) TRANS (pa CONG ([x] c + x))) TRANS ((plus_assoc/n (a*c) c (b*c)) TRANS (SYM ((times/s/Applied a c) CONG ([x] x + b*c)))) 
	

	ind_proof times_comm() : nat()  =
		n = [a, b] DED a * b EQ b * a 
		z = [x] times_z/n x 
	  s = [a, b, pa:n a b] ((times/s/Applied a b) TRANS (pa CONG ([x] b + x))) TRANS (times_right/n b a) 
	

	left_distrib: {a:nat/n, b:nat/n, c:nat/n} DED (a + b) * c EQ a*c + b*c  = [a, b, c] distrib_left/n a b c 
	right_distrib: {a:nat/n, b:nat/n, c:nat/n} DED a * (b + c) EQ a*b + a*c  = [a, b, c] ((times_comm/n a (b+c)) TRANS (distrib_left/n b c a)) TRANS (((times_comm/n b a) CONG ([x] x + (c*a))) TRANS (times_comm/n c a CONG ([x] (a*b) + x))) 

	ind_proof times_assoc() : nat()  =
		n = [a, b, c] DED a * (b * c) EQ (a * b) * c 
		z = [b, c] (times/z/Applied (b*c)) TRANS (SYM (((times/z/Applied b) CONG ([x] x * c)) TRANS (times/z/Applied c))) 
		s = [a, b, c, pa] ((times/s/Applied a (b*c)) TRANS (pa CONG ([x] (b*c) + x))) TRANS (SYM (((times/s/Applied a b) CONG ([x] x * c)) TRANS (distrib_left/n b (a*b) c)))  
	

	inductive_definition predec() : nat()  =
		n: type  = nat/n 
		z: n  = nat/z 
		s: n ⟶ n  = ([u] u) 
  
	
  inductive_definition monus() : nat()  =
		n: type  = (nat/n ⟶ nat/n) 
		z: n  = ([x] x) 
		s: n ⟶ n  = ([u,x] predec/n (u x)) 
  


namespace http://cds.omdoc.org/examples 

import lfx http://gl.mathhub.info/MMT/LFX/TypedHierarchy 
import finite http://gl.mathhub.info/MMT/LFX/Finite 
import rules scala://structuralfeatures.lf.mmt.kwarc.info

theory InductiveTests : ?InductivelyDefinedTypes =
	lst: type ⟶ type  = [a] list1/list a 
	cns: {a:type} a ⟶ lst a ⟶ lst a  = [a, hd, tl] list1/cons a hd tl 

	contraposition: {a: type, b: type, x_a: a, x_b: b, y_a: a, y_b: b} (DED x_a NEQ y_a ⟶ DED x_b NEQ y_b) ⟶ (DED x_b EQ y_b ⟶ DED x_a EQ y_a)  # contra 3 4 5 6 7 
	trans_equal: {a: type, w: a, x: a, y: a, z: a} DED w EQ x ⟶ DED z EQ y ⟶ DED x EQ y ⟶ DED w EQ z  # trans_eq 2 3 4 5 6 7 8 
	cns_functionhood: {a: type, hd_0: a, tl_0: lst a, hd_1, tl_1} DED (hd_0 EQ hd_1) ⟶ DED tl_0 EQ tl_1 ⟶ DED (cns a hd_0 tl_0) EQ (cns a hd_1 tl_1)  # cns_funct 2 3 4 5 6 7 

	
	//cons_inj_0: {a:type, hd_0:a, tl_0: lst a, hd_1:a, tl_1: lst a} DED (cns a hd_0 tl_0) EQ (cns a hd_1 tl_1) ⟶ DED hd_0 EQ hd_1 ❘ = [a, hd_0, tl_0, hd_1,tl_1] contra hd_0 (cns a hd_0 tl_0) hd_1 (cns a hd_1 tl_1) (list1/injective_cons_0 a hd_0 tl_0 hd_1 tl_1) ❙
	//cons_inj_1: {a:type, hd_0:a, tl_0: lst a, hd_1:a, tl_1: lst a} DED (cns a hd_0 tl_0) EQ (cns a hd_1 tl_1) ⟶ DED tl_0 EQ tl_1 ❘ = [a, hd_0, tl_0, hd_1,tl_1] contra tl_0 (cns a hd_0 tl_0) tl_1 (cns a hd_1 tl_1) (list1/injective_cons_1 a hd_0 tl_0 hd_1 tl_1) ❙
	//consArgs: {a: type} type ❘ = [a] a * (lst a) ❙
	//consP: {a: type} consArgs a ⟶ lst a ❘ = [a, args] cns a (pair/a a (lst a) args) (pair/b a (lst a) args) ❙
	// This should work:❙
	// test: {a: type, hd_0: a, tl_0: lst a, hd_1:a, tl_1: lst a} DED (cns a hd_0 tl_0) EQ (cns a hd_1 tl_1) ⟶ DED hd_0 EQ hd_1 ❘ = [a, hd_0, tl_0, hd_1, tl_1] (cons_inj_0 a hd_0 tl_0 hd_1 tl_1) ❙
	// inj_cons: {a: type, hd_0: a, tl_0: lst a, hd_1:a, tl_1: lst a} DED (cns a hd_0 tl_0) EQ (cns a hd_1 tl_1) ⟶ DED pair/make a (lst a) hd_0 tl_0 EQ pair/make a (lst a) hd_1 tl_1 ❘ 
	= [a, hd_0, tl_0, hd_1, tl_1, P] pair/equiv a (lst a) hd_0 tl_0 hd_1 tl_1 (cons_inj_0 a hd_0 tl_0 hd_1 tl_1 P) (cons_inj_1 a hd_0 tl_0 hd_1 tl_1 P) ❙

	// This is correct, but not accepted by the typechecker
	// For the typechecker to see this a (typelevel) definition expansion of consP is required ❙
	// inj_consP_weak: {a: type, args_0: consArgs a, args_1: consArgs a} DED (consP a args_0) EQ (consP a args_1) ⟶ 
		DED pair/make a (lst a) (pair/a a (lst a) args_0) (pair/b a (lst a) args_0) EQ pair/make a (lst a) (pair/a a (lst a) args_1) (pair/b a (lst a) args_1) 
	❘ = [a, args_0, args_1, P] (inj_cons a (pair/a a (lst a) args_0) (pair/b a (lst a) args_0) (pair/b a (lst a) args_1) (pair/b a (lst a) args_1)) P ❙
	// inj_consP: {a: type, args_0: consArgs a, args_1: consArgs a, P: DED (consP a args_0) EQ (consP a args_1)} DED args_0 EQ args_1 ❘ = [a, args_0, args_1, P] 
		trans_equal (a*(lst a)) args_0 (pair/make a (lst a) (pair/a a (lst a) args_0) (pair/b a (lst a) args_0)) (pair/make a (lst a) (pair/a a (lst a) args_1) (pair/b a (lst a) args_1)) args_1
	 (pair/repr a (lst a) (pair/a a (lst a) args_0) (pair/b a (lst a) args_0) args_0)
	 (pair/repr a (lst a) (pair/a a (lst a) args_1) (pair/b a (lst a) args_1) args_1)
	 (inj_consP_weak a args_0 args_1 P) ❙
	
	list: type ⟶ type  = [a] list3/list a 
	//inj_cons_1: {a:type, hd_0:a, tl_0: list a, hd_1:a, tl_1: list a} DED hd_0 NEQ hd_1 ⟶ DED (hd_0 ∷ tl_0) NEQ (hd_1 ∷ tl_1) ❘ = [a, hd_0, tl_0, hd_1, tl_1] list3/injective_cons_0 a hd_0  tl_0 hd_1 tl_1 ❙
	//inj_cons_2: {a:type, hd_0:a, tl_0: list a, hd_1:a, tl_1: list a} DED tl_0 NEQ tl_1 ⟶ DED (hd_0 ∷ tl_0) NEQ (hd_1 ∷ tl_1) ❘ = [a, hd_0, tl_0, hd_1, tl_1] list3/injective_cons_1 a hd_0  tl_0 hd_1 tl_1 ❙
	//weak_inj_cons_1: {a:type, hd_0:a, hd_1:a, tl:list3/list a} DED hd_0 NEQ hd_1 ⟶ DED (hd_0 ∷ tl) NEQ (hd_1 ∷ tl) ❘ = [a, hd_0, hd_1, tl] list3/injective_cons_0 a hd_0 tl hd_1 tl ❙
	//weak_inj_cons_2: {a:type, hd:a, tl_0:list3/list a, tl_1:list3/list a} DED tl_0 NEQ tl_1 ⟶ DED (hd ∷ tl_0) NEQ (hd ∷ tl_1) ❘ = [a, hd, tl_0, tl_1] list3/injective_cons_1 a hd tl_0 hd tl_1 ❙


// theory UniversalPropertyFreeMonoid : ?InductivelyDefinedTypes =
// 	inductive unitType() ❘ =
// 		tp: type ❙
// 		tm: unitType ❙
// 	❚
// 	unit: type ❘ = unitType/tp ❙
// 	plus_assoc: {x: nat/n, y: nat/n, z: nat/n} DED nat/plus/n (nat/plus/n x y) z EQ nat/plus/n x (nat/plus/n y z) ❙
// 	zero_plus: {x: nat/n} DED nat/plus/n nat/z x EQ nat/z ❙
// 	plus_zero: {x: nat/n} DED nat/z EQ nat/plus/n x nat/z ❙

// 	inductive_definition Nat(): freeMonoid(unit) ❘ =
// 		fm: type ❘ = nat/n ❙
// 		gen: a ⟶ fm ❘ = unitType/induct/tm nat/n (nat/s nat/z) ❙
// 		unit: fm ❘ = nat/z ❙
// 		comp: fm ⟶ fm ⟶ fm ❘ = [a, b] nat/plus/n a b ❙
// 		assoc: {x: fm, y: fm, z: fm} DED comp (comp x y) z EQ comp x (comp y z) ❘ = [x, y, z] plus_assoc x y z ❙
// 		unit_r: {x: fm} DED comp x unit EQ x ❘ = [x] zero_plus x ❙
// 		unit_l: {x: fm} DED comp unit x EQ x ❘ = [x] plus_zero x ❙
// 	❚
// ❚

/T The following definition of surreal numbers won't typecheck (as expected), but is a nice pathological example ❙
// theory SurrealNumbers : ?LFXI =
	linear_order: {A: type} A ⟶ type ❙
//	ordBddAboveSet: {A: type, ord: linear_order A} A ⟶ kind ❙
//	ordBddBelowSet: {A: type, ord: linear_order A} A ⟶ kind ❙
	
//	inductive surreal() ❘ =
//		sur: type ❙
//		ord: linear_order sur ❙
//		makeSurreal: {a: sur} (ordBddAboveSet sur ord a) (ordBddBelowSet sur ord a) sur ❙
//	
// ❚
namespace http://cds.omdoc.org/examples

//   theory ObjectLevelInstances : http://cds.omdoc.org/urtheories?LF =
  tp    : type❙
  tm    : type❙
  equal : tm ⟶ tm ⟶ tm  ❘# 1 = 2❙
  of    : tm ⟶ tp ⟶ type❘# 1 # 2❙

  const : tp ⟶ THY❘ = [a] {|
    c  : tm,
    of : c # a
  |}❙
  
  nat  : tp❙
  zero : const nat❙
  
  // alsozero : const nat ❘= [|c : zero/c, of : zero/of|]❙


//  theory MetaLevelInstances : http://cds.omdoc.org/urtheories?LF =
  tp    : type❙
  tm    : type❙
  equal : tm ⟶ tm ⟶ tm  ❘# 1 = 2❙
  of    : tm ⟶ tp ⟶ type❘# 1 # 2❙

  theory const > {|a: tp|}❘ =
    c  : tm❙
    of : c # a❙


//  nat : tp❙
  // structure zero : const nat❙
  
  // alsozero : const nat ❘= [|c : zero/c, of : zero/of|]❙

namespace http://cds.omdoc.org/examples

theory Int : http://cds.omdoc.org/urtheories?LF =
  include ?Nat
  int   : type = nat
  pred  : nat ⟶ nat        # pred 1 prec 20
  uminus: nat ⟶ nat        # - 1 prec 20 
  minus : nat ⟶ nat ⟶ nat  # 1 - 2 prec 10 


theory IntRules : http://cds.omdoc.org/urtheories?LF =
  include ?Int 
  include ?NatRules

  times_mono    : {X:nat,Y:nat,Z:nat} ⊦ O ≤ Z ⟶ ⊦ X ≤ Y ⟶ ⊦ X * Z ≤ Y * Z
  times_invmono : {X,Y,Z} ⊦ O ≤ Z ⟶ ⊦ X * Z ≤ Y * Z ⟶ ⊦ X ≤ Y  
  
  succ_invert    : {X} ⊦ pred (X') = X role Simplify
  plus_invert_R  : {X,Y} ⊦ (X + Y) - Y = X role Simplify
  plus_invert_L  : {X,Y} ⊦ (X + Y) - X = Y role Simplify

namespace http://cds.omdoc.org/examples

theory Equality : ur:?PLF =
  eq : {a: type} a ⟶ a ⟶ type # 2 = 3 prec 0 role Eq
  reflexive : {a,x:a} x = x # refl %I1 %I2


theory List : ur:?PLF =
  include ?Equality
  list : type ⟶ type
  nil  : {a} list a# nil 1
  cons : {a} a ⟶ list a ⟶ list a# 2 %R, 3 prec 10

  embed : {a} a ⟶ list a = [a,x] x , (nil a)# 2 | prec 20

  // the simplification rule generator does not allow fold to have implicit arguments yet❙
  fold : {a,b:type} list a ⟶ b ⟶ (a ⟶ b ⟶ b) ⟶ b
  fold_nil : {a:type,b,n:b,c: a ⟶ b ⟶ b} (fold a b (nil a) n c) = n role Simplify
  fold_cons : {a,b,x,l,n,c:a ⟶ b ⟶ b} (fold a b (x,l) n c) = (c x (fold a b l n c))role Simplify
  
  concat : {a} list a ⟶ list a ⟶ list a= [a,l,m] fold a (list a) l m [x,xs] x,xs # 2 + 3 prec 5



theory Test : ur:?PLF =
  include ?List
  a : type
  c : a
  f : a ⟶ a

  test : (c,c|)+(c,c|) = c,c,c,c|= refl  

namespace http://cds.omdoc.org/examples

import real scala://real.omdoc.org/

rule scala://parser.api.mmt.kwarc.info?MMTURILexer

theory NatLiterals : http://cds.omdoc.org/urtheories?LF =
  include ?NatRules
  include ☞real:?Bool
  include ☞real:?StandardNat
  
  // this only type-checks because ⊦ 1+1 = 2 unifies with ⊦ true ❙
  test  : ⊦ 1+1 = 2 = trueI

  
theory IntLiterals : http://cds.omdoc.org/urtheories?LF =
  include ?IntRules // this should include NatRules, but the last test only works with the rule IntRules?succ_invert/Solve❙
  include ☞real:?Bool
  include ☞real:?StandardInt
  test  : ⊦ 1-3 = -2  = trueI


theory Vectors : http://cds.omdoc.org/urtheories?LF =
  include ?NatLiterals

  a     : type
  c     : a
  
  a_equal : a ⟶ a ⟶ type # 1 = 2 role Eq

  vec   : nat ⟶ type  # vec 1 prec 5
  empty : vec 0  #  
  cons  : {n} vec n ⟶ a ⟶ vec n'  # 2 , 3

  vec_equal : {n} vec n ⟶ vec n ⟶ type # 2 == 3role Eq
  
  append      : {m,n} vec m ⟶ vec n ⟶ vec (m + n)  # 3 @ 4
  // this only type-checks because vec n+0 and vec n are recognized as equal ❙
  appendempty : {n, v: vec n} v @ ∅ == v
  // this only type-checks because vec m + (n') and vec (m + n)' are recognized as being equal ❙
  appendcons  : {m,n, x, v: vec m, w: vec n} v @ (w,x) == (v @ w, x)
  
  last : {n} vec n' ⟶ a  # last 2
  lastcons : {n, x, v: vec n} last (v,x) = x role Simplify
  
  // this only type-checks because vec 3 and vec 0''' are recognized as equal ❙
  test1 : vec 3  = ∅,c,c,c
  // this only type-checks because vec 6 and vec (3+3) are recognized as equal ❙
  test2 : vec 6  = test1 @ test1 
  // this only type-checks because vec n' unifies with vec 3❙
  test3 : a = last test1

namespace http://cds.omdoc.org/examples

//   intuitionistic first-order logic with natural deduction rules and a few example proofs ❚

theory FOL : http://cds.omdoc.org/urtheories?LF =
  include ?PL
  term  : type
  forall : (term ⟶ prop) ⟶ prop#  1 ##  V1 2
  exists : (term ⟶ prop) ⟶ prop#  1 ##  V1 2


theory FOLNatDed : http://cds.omdoc.org/urtheories?LF =
  include ?FOL
  include ?PLNatDed  
  forallI  : {A} ({x} ⊦ (A x)) ⟶ ⊦ ∀ A 
  forallE  : {A} ⊦ (∀ A) ⟶ {x} ⊦ (A x) role ForwardRule

  existsI  : {A} {c} ⊦ (A c) ⟶ ⊦ ∃ [x] (A x) # existsI 2 3
  existsE  : {A,C} ⊦ (∃ [x] A x) ⟶ ({x} ⊦ (A x) ⟶ ⊦ C) ⟶ ⊦ C


theory FOLEQ : http://cds.omdoc.org/urtheories?LF =
  include ?FOL
  equal  : term ⟶ term ⟶ prop# 1  2 prec 30


theory FOLEQNatDed : http://cds.omdoc.org/urtheories?LF =
  include ?FOLEQ
  include ?FOLNatDed  
  refl     : {x} ⊦ x ≐ x
  congT    : {x,y} ⊦ x ≐ y ⟶ {T: term ⟶ term} ⊦ (T x) ≐ (T y) # congT 3 4
  congF    : {x,y} ⊦ x ≐ y ⟶ {F: term ⟶ prop} ⊦ (F x) ⟶ ⊦ (F y)# congF 3 4 5
  sym      : {x,y} ⊦ x ≐ y ⟶ ⊦ y ≐ x
  trans    : {x,y,z} ⊦ x ≐ y ⟶ ⊦ y ≐ z ⟶ ⊦ x ≐ z
  
  trans3   : {w,x,y,z} ⊦ w ≐ x ⟶ ⊦ x ≐ y ⟶ ⊦ y ≐ z ⟶ ⊦ w ≐ z
           = [w,x,y,z,p,q,r] trans (trans p q) r
  trans4   : {v,w,x,y,z} ⊦ v ≐ w ⟶⊦ w ≐ x ⟶ ⊦ x ≐ y ⟶ ⊦ y ≐ z ⟶ ⊦ v ≐ z
           = [v,w,x,y,z,p,q,r,s] trans3 (trans p q) r s

namespace http://cds.omdoc.org/examples

//   higher-order logic❚

theory HOL : ur:?LF =
  include ?TypedTerms
  bool: tp
  Bool = tm bool
  ded : Bool ⟶ type#  1 prec -5role Judgment

  fun : tp ⟶ tp ⟶ tp# 1  2
  lambda: {A,B} (tm A ⟶ tm B) ⟶ tm A → B # λ 3
  apply: {A,B} tm A → B ⟶ tm A ⟶ tm B # 3 @ 4 prec 50

  equalConstant : {A} tm A → (A → bool)
  equal = [A,x,y:tm A] (equalConstant A) @ x @ y# 2 = 3 prec 30
  refl  : {A, X: tm A} ⊦ X = X
  cong  : {A,B,X,Y:tm A} ⊦ X = Y ⟶ {F: tm A ⟶ tm B} ⊦ F X = F Y# 1 cong 5 6 

  beta : {A,B,F: tm A ⟶ tm B, X} ⊦ (λ F) @ X = F X
  
  true = (λ[x:Bool]x) = λ[x]x
  false = (λ[x]x) = λ[x]true
  not = λ[x]x=false
  forall = [A,p: tm A ⟶ Bool] (λ p) = λ[x]true

namespace http://cds.omdoc.org/examples

theory ITP =
  proof # proof 1,
  
  fix    # fix L1T, 2
  assume # assume 1 2
  hence  # hence 1 by 2

  use # use 1, 
  
  localref # ` L1


theory Test : ?ITP =
  include ?FOLEQNatDed
  
//  test : {p: term ⟶ o} ⊦ ∀ [x] p x ⇒ p x❘
       = [p] proof (fix x assume p x; hence p x)❙ 

namespace http://cds.omdoc.org/examples/linear

import rules scala://examples.mmt.kwarc.info

// Linear logic
   Syntax: intuitionistic linear logic
   Proof theory: resource semantics based on Frank Pfenning's lecture notes
   (http://www.cs.cmu.edu/~fp/courses/15816-s10/schedule.html, Lecture 23-24) resource semantics


theory Syntax : http://cds.omdoc.org/urtheories?LF =
   o : type
    : o ⟶ o ⟶ o # 1  2 prec 100
   1 : o
   & : o ⟶ o ⟶ o # 1 & 2 prec 100
    : o
    : o ⟶ o ⟶ o # 1  2 prec 100
   0 : o
    : o ⟶ o ⟶ o # 1  2 prec 80
   ! : o ⟶ o      # ! 1 prec 110
   
    : o ⟶ o ⟶ o # 1  2 prec 80
     = [x,y] !x ⊸ y


// We use untyped first-order logic with equality to define the sematnics.
   The values of the first-order universe are the worlds, and propositions may hold at different worlds.❚

theory Worlds : /examples?FOLEQNatDed = 
   include ?Syntax
   // worlds contain resources ❙
   world : type= term
   // composition of worlds, corresponds to multiset union of resources ❙
   union : world ⟶ world ⟶ world # 1 * 2 prec 100
   // empty world with no resources ❙
   empty : world# ε

   // * is a monoid❙
   neutL  : {P} ⊦ ε*P ≐ P
   neutR  : {P} ⊦ P*ε ≐ P
   assoc  : {P,Q,R} ⊦ (P*Q)*R ≐ P*(Q*R)
   
   // A @ P: A can be produced by using all resources available in world P❙
   at : o ⟶ world ⟶ prop
   At : o ⟶ world ⟶ type = [p,w] ⊦ at p w# 1 @ 2 prec 50role Judgment
   // a formula is valid if it holds in the empty world❙
   valid : o ⟶ type = [A] A @ ε# valid 1 prec -10 
   


// Apart from the monoid/multiset structure, there is no way to introduce worlds.
   The set of worlds is the freely-generated T over the bound world variables.
   Here T is the theory imposed on worlds, T is an extension of the monoid theory.

   Different extensions allow modeling different structural rules.
   The following gives three extensions, but only Exchange is used later on.❚

// Exchange corresponds to commutativity.❚
theory Exchange : /examples?FOLEQNatDed =
  include ?Worlds
   comm : {P,Q} ⊦ P*Q ≐ Q*P

   // We add two special type-checking rules that mechanize the monoid+commutativity axiom.
      Their implementations are given in the folder scala (sibling of source).❙
   
   // A simplification rule for *-terms: it normalizes bracketing of *, drops ε, and reorders the arguments❙
   rule rules?NormalizeWorlds

   test : {p,q,r} ⊦ r*(p*q)*ε*r ≐ r*(r*(q*p)) = [p,q,r] refl

   // An equality-checking rule for equations involving *: it normalizes both sides and solves meta-variables of type world.
      For example, it can reduce v*w=v*w' to w=w'.
      Situations like this came up in several of the examples below.
      This rule is admissible for solving meta-variables but not derivable from the monoid+commutativity axioms.
      Effectively, it works in the freely-generated commutative monoid.
      Because it is only admissible, it breaks modularity: e.g., it cannot be easily combined with a corresponding rule for idempotence.❙
   rule rules?EquateWorlds


// Contraction corresponds to idempotence.❚
theory Contraction : /examples?FOLEQNatDed =
  include ?Worlds
  idem : {P} ⊦ P*P ≐ P


// Weakening corresponds to the empty world being the least element.❚
theory Weakening : /examples?FOLEQNatDed =
  include ?Worlds
   // ordering with monotonicity❙
   weaker : world ⟶ world ⟶ prop  # 1  2 prec 80
   ≤_refl   : {P} ⊦ P ≤ P
   ≤_antisym: {P,Q} ⊦ P ≤ Q ⟶ ⊦ Q ≤ P ⟶ ⊦ P≐Q
   ≤_trans  : {P,Q,R} ⊦ P≤Q ⟶ ⊦ Q≤R ⟶ ⊦ P≤R 
   ≤_monotone: {a,b,c,d} ⊦ a ≤ b ⟶ ⊦ c ≤ d ⟶ ⊦ a*c ≤ b*d 

   // least world (without this, the order is trivial, i.e., there is no weakening)❙
   ≤_least : {P} ⊦ ε ≤ P

   // TODO: This should be a subtyping rule so that it does not occur in proofs.❙
   weaken: {A,v,w} A @ v ⟶ ⊦v≤w ⟶ A @ w
   
   divisibility: {P,Q} ⊦ P ≤ P*Q 
               = [P,Q] congF neutR ([u]u≤P*Q) (≤_monotone ≤_refl ≤_least) 


// Now proofs of the linear sequent A1, ..., An |- A are represented as terms of type
   (A1 ⊗ ... ⊗ An) ⊸ A  @  ε, where @ is the binary holds-at relation between propositions and worlds.❚
theory ResourceSemantics : /examples?FOLEQNatDed =
   include ?Worlds
   include ?Exchange

   ⊗_R  : {A,B,a,b} A @ a ⟶ B @ b ⟶ A ⊗ B @ a*b
   ⊗_L  : {A,B,C,u,v} A ⊗ B @ u ⟶ ({a}{b} A @ a ⟶ B @ b ⟶ C @ a*b*v) ⟶ C @ u*v
   # ⊗_L 6 7

   1_R : 1 @ ε
   1_L : {C,u,v} 1 @ u ⟶ C @ v ⟶ C @ u*v

   &_R  : {A,B,w} A @ w ⟶ B @ w ⟶ A & B @ w
   &_Ll : {A,B,C,u,v} A & B @ u ⟶ ({a} A @ a ⟶ C @ a*v) ⟶ C @ u*v
   &_Lr : {A,B,C,u,v} A & B @ u ⟶ ({b} B @ b ⟶ C @ b*v) ⟶ C @ u*v

   ⊤_R  : {w} ⊤ @ w
   
   ⊕_Rl : {A,B,w} A @ w ⟶ A ⊕ B @ w
   ⊕_Rr : {A,B,w} B @ w ⟶ A ⊕ B @ w
   ⊕_L  : {A,B,C,u,v} A ⊕ B @ u ⟶ ({a} A @ a ⟶ C @ a*v) ⟶ ({b} B @ b ⟶ C @ b*v) ⟶ C @ u*v  

   0_L  : {C,u,v} 0 @ u ⟶ C @ u*v 
   
   ⊸_R  : {A,B,w} ({a} A @ a ⟶ B @ a*w) ⟶ A ⊸ B @ w
   ⊸_L  : {A,B,C,u,a,v} A ⊸ B @ u ⟶ A @ a ⟶ ({b} B @ b ⟶ C @ b*v) ⟶ C @ u*a*v
   // alternatively
   ⊸_E  : A ⊸ B @ P ⟶ A @ Q ⟶ B @ P*Q
   ⊸_L : A ⊸ B @ H ⟶ A @ P ⟶ ({b} B @ b ⟶ C @ b*Q) ⟶ C @ H*P*Q
      = [p][q][f] f (H*P) (⊸E p q)


   !_R : {A} A @ ε ⟶ ! A @ ε
   !_L : {A,C,u,v} ! A @ u ⟶ (A @ ε ⟶ C @ v) ⟶ C @ u*v
   
   
   // In the remainder, we prove some derivable rules to exercise the calculus.❙
   
   ⊗_commute : {A,B} valid A⊗B ⊸ B⊗A
      = [A,B] ⊸_R [ab,h] ⊗_L h [a,b,p,q] ⊗_R q p

   // needs to solve abc * X = abc and ab * Y * X = ab * c, solution: X = epsilon, Y = c❙ 
   ⊗_assoc1 : {A,B,C} valid (A⊗B)⊗C ⊸ A⊗(B⊗C)
        = [A,B,C] ⊸_R [abc,h] ⊗_L h 
              [ab,c,pq,r] ⊗_L pq
                 ([a,b,p,q] ⊗_R p (⊗_R q r))
      
   ⊗_assoc2 : {A,B,C} valid A⊗(B⊗C) ⊸ (A⊗B)⊗C
        = [A,B,C] ⊸_R [abc,h] ⊗_L h 
              [a,bc,p,qr] ⊗_L qr
                 ([b,c,q,r] ⊗_R (⊗_R p q) r)

   ⊗_neutral1 : {A} valid A⊗1 ⊸ A
      = [A] ⊸_R [ao,h] ⊗_L h [a,b,p,q] 1_L q p
   ⊗_neutral2 : {A} valid A ⊸ A⊗1
      = [A] ⊸_R [a,h] ⊗_R h 1_R
      
   ⊕_commute : {A,B} valid A⊕B ⊸ B⊕A
      = [A,B] ⊸_R [ab,h] ⊕_L h ([a,p] ⊕_Rr p) ([b,q] ⊕_Rl q)

   ⊕_neutral1 : {A} valid A⊕0 ⊸ A
    = [A] ⊸_R [az,h] ⊕_L h ([a,p] p) ([z,q] 0_L q)
   ⊕_neutral2 : {A} valid A ⊸ A⊕0
      = [A] ⊸_R [a,h] ⊕_Rl h
   
      
   !_over_⊕ : {A,B} valid (!A⊕!B) ⊸ !(A⊕B)
            = [A,B] ⊸_R [ab,h] ⊕_L h ([a,p] !_L p ([pE] !_R (⊕_Rl pE)))
                                     ([b,q] !_L q ([qE] !_R (⊕_Rr qE)))
   !_over_& : {A,B} valid !(A&B) ⊸ (!A&!B)
          // TODO: This proof unexpectedly does not type-check, eventually failing at a=ε and b=ε.
             Further investigation is needed to determine if the proof is in fact wrong or
             if the type-checker is led astray by the EquateWorlds rule.
          //  = [A,B] ⊸_R [ab,h] &_R (!_L h [pqE] &_Ll pqE ([a,p] !_R p))
                                   (!_L h [pqE] &_Lr pqE ([b,q] !_R q))❙
   !_idempotent1 : {A} valid !!A ⊸ !A
                 = [A] ⊸_R [a,h] !_L h [k] !_L k [l] !_R l 
   !_idempotent2 : {A} valid !A ⊸ !!A
                 = [A] ⊸_R [a,h] !_L h [k] !_R (!_R k)
   !_weaken : {A} valid !A ⊸ A
            = [A] ⊸_R [a,h] !_L h [k] k

namespace http://cds.omdoc.org/examples

// @_title Propositional Logic in MMT❙
// @_author Florian Rabe❙

/T   
Intuitionistic propositional logic with natural deduction rules and a few example proofs ❚

/T We use LF as the meta-theory for all theories in this file.❚
fixmeta http://cds.omdoc.org/urtheories?LF

/T    
We start with the syntax of propositional logic.❚

theory PL =

  # :types The Basic Concepts
  
  /T the type of propositions ❙
  prop  : type 
  
  /T Given [F:prop], the type $⊦ F$ holds the proofs of $F$.❙
  ded   : prop ⟶ type          #  1  prec -5role Judgment
  
  ## Abbreviations
  
  /T The type $contra$ abbreviates the judgment of inconsistency.
     If we can give an element of the type, then every proposition has a proof.❙
  contra : type  = {a} ⊦ a #              

  # Constructors

  /T The constructors provide the expressions of the types above.❙
  
  true  : prop                                   
  false : prop                                   
  and   : prop ⟶ prop ⟶ prop   # 1  2 prec 15
  or    : prop ⟶ prop ⟶ prop   # 1  2 prec 15
  impl  : prop ⟶ prop ⟶ prop   # 1  2 prec 10
  not   : prop ⟶ prop          # ¬ 1   prec 20

  /T Equivalence is taken as a non-primitive here and defined such that for [F:prop,G:prop] we define $F⇔G$ as $(F ⇒ G) ∧ (G ⇒ F)$.❙
  equiv : prop ⟶ prop ⟶ prop   # 1  2 prec 10
        = [x,y] (x ⇒ y) ∧ (y ⇒ x)


/T   Now we describe the proof theory.❚        

theory PLNatDed =
  include ?PL 
  
  /T We use natural ⊦uction proof rules that construct expressions of type $⊦ F$ for some [F:prop].
  {For example, assume two propositions [F: prop, G: prop].
    {If [p:⊦ F, q: ⊦ G], then $andI p q$ is a proof of $F∧G$.}
    {If [p:⊦ F∧G], then $andEl p$ is a proof of $F$.}
  }


  trueI : ⊦ true
  falseE : ⊦ false ⟶ ↯
  andI  : {A,B} ⊦ A ⟶ ⊦ B ⟶ ⊦ A ∧ B   
  andEl : {A,B} ⊦ A ∧ B ⟶ ⊦ A            role ForwardRule
  andEr : {A,B} ⊦ A ∧ B ⟶ ⊦ B            role ForwardRule

  orIl  : {A,B} ⊦ A ⟶ ⊦ A ∨ B           
  orIr  : {A,B} ⊦ B ⟶ ⊦ A ∨ B           
  orE   : {A,B,C} ⊦ A ∨ B ⟶ (⊦ A ⟶ ⊦ C) ⟶ (⊦ B ⟶ ⊦ C) ⟶ ⊦ C
  
  impI  : {A,B} (⊦ A ⟶ ⊦ B) ⟶ ⊦ A ⇒ B 
  impE  : {A,B} ⊦ A ⇒ B ⟶ ⊦ A ⟶ ⊦ B    role ForwardRule

  notI  : {A} (⊦ A ⟶ ↯) ⟶ ⊦ ¬ A# notI 2
  notE  : {A} ⊦ ¬ A ⟶ ⊦ A ⟶ ↯  # notE 2 3 role ForwardRule

  equivI : {A,B} (⊦ A ⟶ ⊦ B) ⟶ (⊦ B ⟶ ⊦ A) ⟶ ⊦ A ⇔ B  
         = [A,B,p,q] andI (impI [x] p x) (impI [x] q x)  
         
  equivEl : {A,B} ⊦ A ⇔ B ⟶ ⊦ A ⟶ ⊦ B  role ForwardRule
          = [A,B,p,a] impE (andEl p) a 
  equivEr : {A,B} ⊦ A ⇔ B ⟶ ⊦ B ⟶ ⊦ A  role ForwardRule
          = [A,B,p,b] impE (andEr p) b 
        
  imp2I : {A,B,C} (⊦ A ⟶ (⊦ B ⟶ ⊦ C)) ⟶ ⊦ A ⇒ (B ⇒ C) 
        = [A,B,C] [f] impI [p] (impI ([q] f p q))             
  
  imp2E : {A,B,C} ⊦ A ⇒ (B ⇒ C) ⟶ ⊦ A ⟶ ⊦ B ⟶ ⊦ C    
        = [A,B,C] [p,q,r] impE (impE p q) r                   

  example : {A} ⊦ A ⇒ (A ∧ A)  
          = [A]impI [p]andI p p


theory DeclarativeProofs =
  include ?PL

  cut : {A,B} ⊦A ⟶ (⊦A ⟶ ⊦B) ⟶ ⊦B
      = [A,B,p,q] q p # PROVE 1 BY 3 4
  
  have : {A} ⊦A ⟶ ⊦A = [A,p] p # HAVE 1 BY 2


theory Declarative_PL =
  include ?PLNatDed
  include ?DeclarativeProofs
  
  decl_trueI = trueI # TRIVIAL
  
  decl_falseE = falseE # EXFALSO 1 
  
  decl_andE : {A,B,C} ⊦ A∧B ⟶ (⊦A ⟶ ⊦B ⟶ ⊦C) ⟶ ⊦C
            = [A,B,C,p,q] q (andEl p) (andEr p) # FROM 4 OBTAIN 5   
  
  decl_orE  = orE # SPLIT 4 CASE 5 CASE 6 prec -10050
  
  decl_impI = impI  # SUPPOSE 1 3 prec 500
  
  example: {A,B,C} ⊦ A∧B ⇒ ((B⇒C)∨C ⇒ C)  = [A,B,C]
    SUPPOSE (A∧B) [ab]▪
    SUPPOSE ((B⇒C)∨C) [bc]▪
    PROVE B BY (
      FROM ab OBTAIN [a,b]▪
      HAVE B BY b
    )[b]▪
    SPLIT bc
      CASE [r] HAVE C BY ≪⊦C≫
      CASE [r] HAVE C BY r
  
  
  example2: {A,B,C} ⊦ A∧B ⇒ ((B⇒C)∨C ⇒ C) = [A,B,C] impI[p]impI[q]orE q ([r] impE r (andEr p)) ([r]r)


import rules scala://lf.mmt.kwarc.info
theory ProofIrrelevance =
  include ?PL
  /T a rule that makes all terms of type ded F equal❙
  rule rules?TermIrrelevanceRule ded

namespace http://cds.omdoc.org/examples

fixmeta ur:?LF

theory ProverTest =

  a: type
  b: type
  c: type
  d: type

  k: a
  r: a ⟶ b role ForwardRule
  s: a ⟶ b ⟶ c role ForwardRule
  t: a ⟶ b ⟶ c ⟶ d
  
  q: d ⟶ d
  
  test : a ⟶ a ⟶ d  = ≪a ⟶ a ⟶ d ≫


theory PLProofs =
  include ?PLNatDed
  include ?ProofIrrelevance
  
  /T Not all of the automated proofs work at the moment. ❙

  test  : {a,b} ⊦ (a ∧ b) ⇒ (b ∧ a) = _
  test2 : {a,b} ⊦ (a ∨ b) ⇒ (b ∨ a) = _

  interactive_example : {A} ⊦ A ⇒ (A ∧ A)
                      = ≪{A:prop}⊦A⇒A∧A≫ 


theory FOLProofs =
  include ?FOLNatDed
  test  : {f} ⊦ (forall [x] forall [y] f x y) ⇒ (forall [y] forall [x] f x y) 
  // = _
  test2 : {f} ⊦ (exists [x] exists [y] f x y) ⇒ (exists [y] exists [x] f x y) 
  // = _


namespace http://cds.omdoc.org/examples

// like fol.mmt but for sorted first-order logic ❚

theory TypedTerms : ur:?LF =
  tp: type
  tm: tp ⟶ type# tm 1 prec -5


theory SFOL : http://cds.omdoc.org/urtheories?LF =
  include ?PL
  include ?TypedTerms
  forall : {S} (tm S ⟶ prop) ⟶ prop#  2                           
  exists : {S} (tm S ⟶ prop) ⟶ prop#  2


theory SFOLEQ : http://cds.omdoc.org/urtheories?LF =
  include ?SFOL
  equal  : {S} tm S ⟶ tm S ⟶ prop# 2  3 prec 30


theory SFOLNatDed : http://cds.omdoc.org/urtheories?LF =
  include ?SFOL
  include ?PLNatDed  
  forallI  : {S,A} ({x: tm S} ⊦ (A x)) ⟶ ⊦ ∀ A 
  forallE  : {S,A} ⊦ (∀ A) ⟶ {x: tm S} ⊦ (A x) role ForwardRule

  existsI  : {S,A} {c} ⊦ (A c) ⟶ ⊦ ∃ [x: tm S] (A x) # existsI 2 3
  existsE  : {S,A,C} ⊦ (∃ [x: tm S] A x) ⟶ ({x} ⊦ (A x) ⟶ ⊦ C) ⟶ ⊦ C


theory Declarative_SFOL =
  include ?SFOLNatDed
  include ?DeclarativeProofs
  
  decl_forallI = forallI # ASSUME 3
  decl_existsI = existsI # TAKE 3 4


theory SFOLEQNatDed : http://cds.omdoc.org/urtheories?LF =
  include ?SFOLEQ
  include ?SFOLNatDed  
  refl     : {S,x: tm S} ⊦ x ≐ x
  congT    : {S, T, x,y} ⊦ x ≐ y ⟶ {F: tm S ⟶ tm T} ⊦ (F x) ≐ (F y) # congT 3 4
  congF    : {S, x,y: tm S} ⊦ x ≐ y ⟶ {F: tm S ⟶ prop} ⊦ (F x) ⟶ ⊦ (F y)# congF 3 4 5
  sym      : {S, x,y: tm S} ⊦ x ≐ y ⟶ ⊦ y ≐ x
  trans    : {S, x,y,z: tm S} ⊦ x ≐ y ⟶ ⊦ y ≐ z ⟶ ⊦ x ≐ z
  
  trans3   : {S, w,x,y,z: tm S} ⊦ w ≐ x ⟶ ⊦ x ≐ y ⟶ ⊦ y ≐ z ⟶ ⊦ w ≐ z
           = [S, w,x,y,z,p,q,r] trans (trans p q) r
  trans4   : {S, v,w,x,y,z: tm S} ⊦ v ≐ w ⟶⊦ w ≐ x ⟶ ⊦ x ≐ y ⟶ ⊦ y ≐ z ⟶ ⊦ v ≐ z
           = [S, v,w,x,y,z,p,q,r,s] trans3 (trans p q) r s

namespace http://cds.omdoc.org/examples

theory Magma : ?FOLEQNatDed =
  op : term ⟶ term ⟶ term # 1  2 prec 50


theory Semigroup : ?FOLEQNatDed =
  include ?Magma
  assoc: {x,y,z} ⊦ (x∘y)∘z ≐ x∘(y∘z)
  
  assocR: {x,y,z} ⊦ x∘(y∘z) ≐ (x∘y)∘z
        = [x,y,z] sym assoc

  assoc4:  {w,x,y,z} ⊦ ((w∘x)∘y)∘z ≐ w∘(x∘(y∘z))
        =  [w,x,y,z] trans3 (congT assoc [u]u∘z) assoc (congT assoc [u]w∘u)
  assoc4R: {w,x,y,z} ⊦ w∘(x∘(y∘z)) ≐ ((w∘x)∘y)∘z
        = [w,x,y,z] sym assoc4
  assoc5: {v,w,x,y,z} ⊦ (((v∘w)∘x)∘y)∘z ≐ v∘(w∘(x∘(y∘z)))
        = [v,w,x,y,z] trans4 (congT assoc4 [u]u∘z) assoc
                              (congT assoc [u]v∘u) (congT assoc [u]v∘(w∘u))


theory Commutative : ?FOLEQNatDed =
  include ?Magma
  comm: {x,y} ⊦ x∘y ≐ y∘x


theory Neutral : ?FOLEQNatDed =
  include ?Magma
  e  : term   
  neutLeft: {x} ⊦ x∘e ≐ x
  neutRight: {x} ⊦ x∘e ≐ x


theory Idempotent : ?FOLEQNatDed =
  include ?Magma
  idempotent: {x} ⊦ x∘x ≐ x


theory Monoid : ?FOLEQNatDed =
  include ?Semigroup
  include ?Neutral


theory Band : ?FOLEQNatDed =
  include ?Semigroup
  include ?Idempotent


theory Semilattice : ?FOLEQNatDed =
  include ?Band
  include ?Commutative

namespace http://cds.omdoc.org/examples

fixmeta ur:?LF

/T Multi-adjunctive meta-language (MAM), following the paper "On the Expressive Power of user-defined effects".
   Formalized during Florian Rabe's visit to Matija Pretnar in June 2019❚

theory MAM =
  # Types
  
  vtp : type
  eff : type
  ctp : eff ⟶ type
  
  unit : vtp
  vprod : vtp ⟶ vtp ⟶ vtp# 1 × 2 prec 30
  sum  : vtp ⟶ vtp ⟶ vtp# 1 + 2 prec 30
  Thunk : {e} ctp e ⟶ vtp# U 2 prec 30
  
  Ret : {e} vtp ⟶ ctp e# F 1 2
  fun : {e} vtp ⟶ ctp e ⟶ ctp e# 2  3 prec 30
  cprod : {e} ctp e ⟶ ctp e ⟶ ctp e# 2 & 3 prec 30
  
  # Terms
  
  vtm : vtp ⟶ type# vtm 1 prec -5
  ctm : {e} ctp e ⟶ type# ctm 2 prec -5
  
  empty : eff# 
  
  unitterm : vtm unit# O

  pair : {A,B} vtm A ⟶ vtm B ⟶ vtm A × B# 3 , 4
  pcase : {A,B,e,C: ctp e} vtm A×B ⟶ (vtm A ⟶ vtm B ⟶ ctm C) ⟶ ctm C
  
  inj1 : {A,B} vtm A ⟶ vtm A + B
  inj2 : {A,B} vtm B ⟶ vtm A + B
  scase : {A,B,e,C: ctp e} vtm A+B ⟶ (vtm A ⟶ ctm C) ⟶ (vtm B ⟶ ctm C) ⟶ ctm C
  
  thunk : {e, C: ctp e} ctm C ⟶ vtm U C# T{ 3 } prec -10
  
  force : {e, C: ctp e} vtm U C ⟶ ctm C# 3 ! prec 50
  ret : {A, e} vtm A ⟶ ctm F e A
  
  bind : {A, e, C: ctp e} ctm F e A ⟶ (vtm A ⟶ ctm C) ⟶ ctm C# 4 ; 5
  
  lambda : {A,e,C: ctp e} (vtm A ⟶ ctm C) ⟶ ctm A → C# λ 4
  apply : {A,e,C: ctp e} ctm A → C ⟶ vtm A ⟶ ctm C# 4 @ 5
  
  cpair : {e,C,D: ctp e} ctm C ⟶ ctm D ⟶ ctm C & D# 4 ,, 5
  prj1 : {e,C,D:ctp e} ctm C & D ⟶ ctm C
  prj2 : {e,C,D:ctp e} ctm C & D ⟶ ctm D


theory EFF =
  include ?MAM
  
  Op : type
  Opeff : type
  opeff : Op ⟶ vtp ⟶ vtp ⟶ Opeff# 1 2  3
  opcons : Opeff ⟶ eff ⟶ eff# 1  2
  
  handler : vtp ⟶ eff ⟶ {e:eff} ctp e ⟶ type# 1 2  4  
  rethandler : {A,e,C: ctp e} (vtm A ⟶ ctm C) ⟶ A ∅ ⟹ C# hret 4
  ophandler  : {o,A1,A2,B,e,f,C: ctp f}
               B e ⟹ C ⟶
               (vtm A1 ⟶ vtm U (A2 → C) ⟶ ctm C) ⟶
               B ((o A1 ⇒ A2) ⊎ e) ⟹ C
               # hop 8 9
  
  subsumed : Opeff ⟶ eff ⟶ type# 1  2
  
  op : {o, A, B, e} (o A ⇒ B) ∈ e ⟶ vtm A ⟶ ctm F e B# op 4 5
  handle : {A, e, f, C: ctp f} ctm F e A ⟶ A e ⟹ C ⟶ ctm C# handle 5 with 6


theory Monads =
  include ?MAM
  Monad : {e} (vtp ⟶ ctp e) ⟶ type
  
  monad : {e, C: vtp ⟶ ctp e}
              ({a:vtp} vtm a ⟶ ctm C a) ⟶
              ({a,b} vtm U (C a) ⟶ vtm U (a → C b) ⟶ ctm C b) ⟶
              Monad e C# where 3 ; 4
  moncons : {e,C} Monad e C ⟶ eff# 1  3
  refl : {A, e, C, M: Monad e C}
         ctm (C A) ⟶
         ctm F (e ≺ M) A# μ 5
  reify : {A,e,C,M: Monad e C} ctm F (e ≺ M) A ⟶ ctm (C A)# reify 4 5


theory DelimitedContinuations =
  include ?MAM
  dccons : {e} ctp e ⟶ eff
  
  shift : {A, e, C: ctp e} (vtm U (A → C) ⟶ ctm C) ⟶
                           ctm F (dccons e C) A# S0 4  
  reset : {A, e, C: ctp e} ctm F e A ⟶ (vtm A ⟶ ctm C) ⟶ ctm C# 4 | 5 


theory ContinuationMonad =
  include ?Monads
  cont : {e, C: ctp e} vtp ⟶ ctp e= [e,C,a] (U (a → C)) → C# cont 2 3
  contmon : {e, C: ctp e} Monad e [a] cont C a
          = [e,C] where ([a,x] λ[c] c! @ x) ;
               [a,b,m,f] λ[c] m! @ T{λ[y] f! @ y @ c}# contmon 2 


view delMon : ?DelimitedContinuations -> ?ContinuationMonad =
  include ?MAM
  dccons = [e,C] e ≺ contmon C
  shift = [A,e,C,p] μ λ p
  /T The next declarations has a typing error:
     We have p: ctm F e A, but we need
     ctm F (e ≺ contmon C) A.
     (Here ≪T≫ denotes a missing term of type T.)

  reset = [A,e,C,p: ctm F e A,r]
    (reify (contmon C) ≪ctm F (e ≺ contmon C) A≫) @ T{λ r}

namespace http://cds.omdoc.org/naproche-sad

// NaprocheSad is based on the Sad system, which uses the ForTheL language. 
   See http://nevidal.org/sad.en.html, in particular for the full grammar.
   This is a preliminary formalization made live while listening to a talk by Peter Koepke, the main developer.


theory NaprocheSad : ur:?LF =
  set : type
  // sets may be undefined❙
  
  prop : type
  
  // binary connectives assume the (negation of the) first argument to show definedness of the second one❙

  equality : set ⟶ set ⟶ prop
  
  elementof : set ⟶ set ⟶ prop

  notion : type
  is_a   : set ⟶ notion ⟶ type# 1 is a 2

  Elem : notion ⟶ type# Elem 1
  
  // unclear ❙
  function: set ⟶ set ⟶ notion # 1  2 prec 10
  Dom  : {a,b} Elem a → b ⟶ set
  apply: {a,b} Elem a → b ⟶ set
  
  // unclear:❙
  // special expressions: no N, every N for notions N❙
  
  // syntax of linguistic predicates:
     is, e.g., x is less than y
     is a: x is an element of y
     does: x converges to y
     has:  x has unit y❙
  
  // declarations:
     * signature extension: function, predicate, notion
     * definition: function, predicate, notion
     * axiom
     * theorem
     Every declaration has an internal structure of low-level declarations: assumptions, affirmations, selection (exists-elimination), case distinction (or-elimination), local definition.
     Every theorem has exactly one affirmation, which occurs at the end.❙ 
     
  // declarations are elaborated into untyped first-order logic (signature declarations are implicit)❙

  // ontological correctness: all terms are defined (part of verification)❙
  
  // after elaboration, verification generates proof oblibations for ontological correctness and  proof steps (one task per low-level declaration)❙
  
  // A proof step may change the proof goal:
     * if a proof of A∧B is expected and a proof of A is provided, the proof goal changes to B
     * also for proofs of negation-inverted implication
     * also for case distinction (old thesis is relativized by disjunction of cases)
     * also for user-defined symbols like subset (unclear how the system knows about that)

 
  // combination of internal and external reasoning and the generated proof obligations (back and forth)
    * external provers do not see all ZFC axioms, e.g., only relevant instantiations of extensionality



namespace http://cds.omdoc.org/examples

theory Bool : http://cds.omdoc.org/urtheories?LF =
  bool  : type
  true  : bool
  false  : bool


theory Logic : http://cds.omdoc.org/urtheories?LF =
  include ?Bool
  ded   : bool ⟶ type #  1 prec -5  role Judgment
  trueI : ⊦ true

  
theory Nat : http://cds.omdoc.org/urtheories?LF =
  nat   : type
  zero  : nat              # O 
  succ  : nat ⟶ nat       # 1 ' prec 20
  one   : nat             
        = zero'            # I 
  plus  : nat ⟶ nat ⟶ nat  # 1 + 2 prec 10 
  times : nat ⟶ nat ⟶ nat  # 1 * 2 prec 15 
  
  include ?Bool
  equal : nat ⟶ nat ⟶ bool  # 1 = 2 prec 5role Eq
  leq   : nat ⟶ nat ⟶ bool  # 1  2 prec 5


theory NatRules : http://cds.omdoc.org/urtheories?LF =
  include ?Logic
  include ?Nat 

  refl  : {X} ⊦ X = X  
  sym   : {X,Y} ⊦ X = Y ⟶ ⊦ Y = X 
  trans : {X,Y,Z} ⊦ X = Y ⟶ ⊦ Y = Z ⟶ ⊦ X = Z 
  
  eq_leq : {X,Y,Z} ⊦ X = Y ⟶ ⊦ Y ≤ Z ⟶ ⊦ X ≤ Z  
  leq_eq : {X,Y,Z} ⊦ X ≤ Y ⟶ ⊦ Y = Z ⟶ ⊦ X ≤ Z  
  
  plus_comm  : {X,Y} ⊦ X + Y = Y + X  
  plus_assoc : {X,Y,Z} ⊦ (X + Y) + Z = X + (Y + Z) 
  plus_neut_Ex : {X} ⊦ X + O = X  # %%prefix 0 1
  plus_neut_L  : {X} ⊦ O + X = X = [X] trans plus_comm (plus_neut_Ex X) role Simplify 
  plus_neut    : {X} ⊦ X + O = X  = [X] plus_neut_Ex X role Simplify 
  
  plus_succ_R : {X,Y} ⊦ X + Y' = (X+Y)'role Simplify 
  plus_succ_L : {X,Y} ⊦ X' + Y = (X+Y)'role Simplify 
  
  times_comm  : {X,Y} ⊦ X * Y = Y * X  
  times_assoc : {X,Y,Z} ⊦ (X * Y) * Z = X * (Y * Z)  
  times_neut  : {X} ⊦ X * I = Xrole Simplify  
  
  times_zero  : {X} ⊦ X * O = Orole Simplify  
  times_succ_R : {X,Y} ⊦ X * Y' = (X*Y) + Xrole Simplify 
  times_succ_L : {X,Y} ⊦ X' * Y = (X*Y) + Xrole Simplify 

  distrib     : {X,Y,Z} ⊦ X * (Y + Z) = X * Y + X * Zrole Simplify
  
  leq_refl    : {X} ⊦ X≤X  
  leq_trans   : {X,Y,Z} ⊦ X≤Y ⟶ ⊦ Y≤Z ⟶ ⊦ X≤Z    
  leq_antisym : {X,Y} ⊦ X≤Y ⟶ ⊦ Y≤X ⟶ ⊦ X=Y      
  
  plus_mono     : {X,Y,Z} ⊦ X≤Y ⟶ ⊦ X+Z ≤ Y+Z  
  plus_mono_L   : {X,Y,Z} ⊦ X≤Y ⟶ ⊦ Z+X ≤ Z+Y   
                = [X,Y,Z,p] leq_eq (eq_leq plus_comm (plus_mono p)) plus_comm
  plus_invmono  : {X,Y,Z} ⊦ X+Z≤Y+Z ⟶ ⊦ X≤Y  

  theory NatOnly : http://cds.omdoc.org/urtheories?LF =
    least         : {X} ⊦ O ≤ X 
    plus_larger_L : {X,Y} ⊦ X≤X+Y  
                  = [X][Y] eq_leq (sym plus_neut) (plus_mono_L least)  
    plus_larger_R : {X,Y} ⊦ Y≤X+Y  
                  = [X][Y] leq_eq plus_larger_L plus_comm
    times_mono    : {X,Y,Z} ⊦ X ≤ Y ⟶ ⊦ X * Z ≤ Y * Z  
    times_invmono : {X,Y,Z} ⊦ X * Z ≤ Y * Z ⟶ ⊦ X ≤ Y  
  

  
theory NatMinus : http://cds.omdoc.org/urtheories?LF =
  include ?NatRules 
  include ?NatRules/NatOnly
 
  // A partial subtraction operation that takes a proof of definedness as a 3rd argument. ❙
  minus    : {X,Y} ⊦ Y≤X ⟶ nat   # 1 - 2 ! 3 prec 15   ## 1 - 2 %I3
  minus_pi : {X,Y,P,Q} ⊦ X-Y!P = X-Y!Q                  

  minus_intro_L : {X,Y,Z} {p: ⊦ X+Y=Z} ⊦ Z-Y!(leq_eq plus_larger_R p) = X  
  minus_intro_R : {X,Y,Z} {p: ⊦ X+Y=Z} ⊦ Z-X!(leq_eq plus_larger_L p) = Y   
                = [X,Y,Z] [p] trans minus_pi (minus_intro_L (trans plus_comm p))
  minus_elim    : {X,Y,Z,P} ⊦ Z-Y!P = X  ⟶  ⊦ X+Y = Z                      

  
  // minus_inverse : {X} ⊦ X-X!leq_refl = O  ❘
                = [X] trans minus_pi (minus_intro_R (plus_neut_Ex X)) ❙
  // minus_neut    : {X} ⊦ X-O!least = X ❘
                = [X] trans minus_pi (minus_intro_L (plus_neut_Ex X))  ❙
  // also provable: associativity +- (maybe X-(Y+Z)=(X-Y)-Z must be axiom) and distributivity *- ❙

namespace http://cds.omdoc.org/examples

theory FOLPatterns : ur:?LFS =
  include ?FOL
  
  pattern fun(n:NAT)# L1 : 2 =
    f: term^n ⟶ term
  


theory Monoid : ?FOLPatterns =
  fun comp : 2

namespace http://cds.omdoc.org/examples

import real scala://real.omdoc.org/
import rules scala://mmt.kwarc.info

rule scala://parser.api.mmt.kwarc.info?MMTURILexer

//   A first test case for writing imperative programs as MMT theories. ❚
theory ProgLang : http://cds.omdoc.org/urtheories?CF =
  include ☞real:?Bool
  include ?NatRules
  include ☞real:?StandardNat
  
  print : {a: type} a ⟶ None # print 2
  rule rules/cf?Print


theory Counter : ?ProgLang =
  counter: nat= 0
  add: nat ⟶ None= [n] counter = counter + n
  
  
theory Program : ?ProgLang =
  main = print 1

  // This one is still experimental.❙
  // main2 =
    var c = new examples?Counter in
    c.add 3;
    print c.add


namespace http://cds.omdoc.org/examples/programs

import rules scala://mmt.kwarc.info

theory Machine : http://cds.omdoc.org/urtheories?LF =
  obj: type
  loc: type
  
  command: type

  add: obj ⟶ loc ⟶ command
  get: loc ⟶ obj ⟶ command
  update: loc ⟶ obj ⟶ command
  delete: loc ⟶ obj ⟶ command

  chan: type
  stdio: chan
  in : chan ⟶ obj ⟶ command
  out: chan ⟶ obj ⟶ command
  
  execute: command ⟶ type

namespace http://cds.omdoc.org/examples/programs

theory Syntax : http://cds.omdoc.org/urtheories?LF =
  tp: type
  Bool: tp
  Nat : tp
  Unit: tp

  prog: tp ⟶ type

  true : prog Bool
  false: prog Bool
  unit : prog Unit
  zero : prog Nat
  succ : prog Nat ⟶ prog Nat# succ 1
  one  : prog Nat
       = succ zero 
  equal : {a} prog a ⟶ prog a ⟶ prog Bool  # 2 = 3 prec 10
  not   : prog Bool ⟶ prog Bool            # ¬ 1   prec 8 
  plus  : prog Nat ⟶ prog Nat ⟶ prog Nat   # 1 + 2 prec 20
  minus : prog Nat ⟶ prog Nat ⟶ prog Nat   # 1 - 2 prec 20
  
  seq   : {a,b} prog a ⟶ prog b ⟶ prog b           # 3 ; 4 prec 5
  ifte  : {a} prog Bool ⟶ prog a ⟶ prog a ⟶ prog a # if 2 then 3 else 4 prec 3
  ifte2 : prog Bool ⟶ prog Unit ⟶ prog Unit
        = [b,c] if b then c else unit
  while : prog Bool ⟶ prog Unit ⟶ prog Unit

  print : {a} prog a ⟶ prog Unit # print 2
  read  : {a} prog a
  
  val : {a,b} prog a ⟶ (prog a ⟶ prog b) ⟶ prog b # val 3 4

  Var : tp ⟶ type
  var : {a,b} prog a ⟶ (Var a ⟶ prog b) ⟶ prog b # var 3 4
  varref : {a} Var a ⟶ prog a # 2 ' prec 30
  assign : {a} Var a ⟶ prog a ⟶ prog Unit # 2  3 prec 10

  
theory Test : ?Syntax =
  main = val (read Nat) [x]
         var zero [y]
         while (¬ x = y') (
           print x;
           y ← succ y'
         )



theory Machine : http://cds.omdoc.org/urtheories?LF =
  obj: type
  loc: type
  
  command: type

  add: obj ⟶ loc ⟶ command
  get: loc ⟶ obj ⟶ command
  update: loc ⟶ obj ⟶ command
  delete: loc ⟶ obj ⟶ command

  chan: type
  stdio: chan
  in : chan ⟶ obj ⟶ command
  out: chan ⟶ obj ⟶ command
  
  execute: command ⟶ type


theory OperationalSemantics : http://cds.omdoc.org/urtheories?LF =
  include ?Syntax
  include ?Machine
 
  objectify : {a} prog a ⟶ obj   # objectify 2
  varloc: {a} Var a ⟶ loc ⟶ type # 2 @ 3
  
  eval : {a} prog a ⟶ prog a ⟶ type # 2  3 prec 3

  eval_seq: {a,b, p:prog a, q: prog b, x,y} p⟿x ⟶ q⟿y ⟶ p;q ⟿ y
  
  eval_if_true : {a, c, t,e: prog a, x} c⟿true ⟶ t⟿x ⟶ if c then t else e ⟿ x
  eval_if_false: {a, c, t,e: prog a, x} c⟿false ⟶ e⟿x ⟶ if c then t else e ⟿ x
  
  eval_while_true : {c, b, x, y} c⟿true ⟶ b⟿x ⟶ while c b ⟿ y ⟶ while c b ⟿ y
  eval_while_false: {c, b} c⟿false ⟶ while c b ⟿ unit
  
  eval_var    : {a,b, p: prog a, cont: Var a ⟶ prog b, l, x, y}
                p⟿x ⟶ execute (add (objectify x) l) ⟶ ({v} v@l ⟶ cont v ⟿ y)
              ⟶ (var p cont)⟿y
             
  eval_varref : {a,v:Var a,l,x}
                v@l ⟶ execute (get l (objectify x))
              ⟶ v' ⟿ x
              
  eval_assign : {a, v: Var a,p,l,x}
                p⟿x ⟶ v@l ⟶ execute (update l (objectify x))
              ⟶ v←p ⟿ unit
  
  eval_print  : {a, p: prog a, x}
                p⟿x ⟶ execute (out stdio (objectify x))
              ⟶ (print p) ⟿ unit
  
  eval_read   : {a, x: prog a}
                execute (in stdio (objectify x))
              ⟶ (read a) ⟿ x

namespace http://cds.omdoc.org/examples/programs

theory OperationalSemantics : http://cds.omdoc.org/urtheories?LF =
  include ?Syntax
  include ?Machine
 
  objectify : {a} prog a ⟶ obj   # objectify 2
  varloc: {a} Var a ⟶ loc ⟶ type # 2 @ 3
  
  eval : {a} prog a ⟶ prog a ⟶ type # 2  3 prec 3

  eval_seq: {a,b, p:prog a, q: prog b, x,y} p⟿x ⟶ q⟿y ⟶ p;q ⟿ y
  
  eval_if_true : {a, c, t,e: prog a, x} c⟿true ⟶ t⟿x ⟶ if c then t else e ⟿ x
  eval_if_false: {a, c, t,e: prog a, x} c⟿false ⟶ e⟿x ⟶ if c then t else e ⟿ x
  
  eval_while_true : {c, b, x, y} c⟿true ⟶ b⟿x ⟶ while c b ⟿ y ⟶ while c b ⟿ y
  eval_while_false: {c, b} c⟿false ⟶ while c b ⟿ unit
  
  eval_var    : {a,b, p: prog a, cont: Var a ⟶ prog b, l, x, y}
                p⟿x ⟶ execute (add (objectify x) l) ⟶ ({v} v@l ⟶ cont v ⟿ y)
              ⟶ (var p cont)⟿y
             
  eval_varref : {a,v:Var a,l,x}
                v@l ⟶ execute (get l (objectify x))
              ⟶ v' ⟿ x
              
  eval_assign : {a, v: Var a,p,l,x}
                p⟿x ⟶ v@l ⟶ execute (update l (objectify x))
              ⟶ v←p ⟿ unit
  
  eval_print  : {a, p: prog a, x}
                p⟿x ⟶ execute (out stdio (objectify x))
              ⟶ (print p) ⟿ unit
  
  eval_read   : {a, x: prog a}
                execute (in stdio (objectify x))
              ⟶ (read a) ⟿ x

namespace http://cds.omdoc.org/examples/programs

theory Syntax : http://cds.omdoc.org/urtheories?LF =
  tp: type
  Bool: tp
  Nat : tp
  Unit: tp

  prog: tp ⟶ type

  true : prog Bool
  false: prog Bool
  unit : prog Unit
  zero : prog Nat
  succ : prog Nat ⟶ prog Nat# succ 1
  one  : prog Nat
       = succ zero 
  equal : {a} prog a ⟶ prog a ⟶ prog Bool  # 2 = 3 prec 10
  not   : prog Bool ⟶ prog Bool            # ¬ 1   prec 8 
  plus  : prog Nat ⟶ prog Nat ⟶ prog Nat   # 1 + 2 prec 20
  minus : prog Nat ⟶ prog Nat ⟶ prog Nat   # 1 - 2 prec 20
  
  seq   : {a,b} prog a ⟶ prog b ⟶ prog b           # 3 ; 4 prec 5
  ifte  : {a} prog Bool ⟶ prog a ⟶ prog a ⟶ prog a # if 2 then 3 else 4 prec 3
  ifte2 : prog Bool ⟶ prog Unit ⟶ prog Unit
        = [b,c] if b then c else unit
  while : prog Bool ⟶ prog Unit ⟶ prog Unit

  print : {a} prog a ⟶ prog Unit # print 2
  read  : {a} prog a
  
  val : {a,b} prog a ⟶ (prog a ⟶ prog b) ⟶ prog b # val 3 4

  Var : tp ⟶ type
  var : {a,b} prog a ⟶ (Var a ⟶ prog b) ⟶ prog b # var 3 4
  varref : {a} Var a ⟶ prog a # 2 ' prec 30
  assign : {a} Var a ⟶ prog a ⟶ prog Unit # 2  3 prec 10

  
theory Test : ?Syntax =
  main = val (read Nat) [x]
         var zero [y]
         while (¬ x = y') (
           print x;
           y ← succ y'
         )

namespace http://cds.omdoc.org/physics

theory Quantities : ur:?LF =
   include examples?Real

   // the type of dimensions, e.g., time, length ❙
   dim : type
   scalar: dim
   mult_dim   : dim ⟶ dim ⟶ dim             # 1 * 2
   inv_dim    : dim ⟶ dim                   # 1  prec 10

   div_dim    : dim ⟶ dim ⟶ dim = [d,e] d*e⁻ # 1 / 2
   square_dim : dim ⟶ dim= [d] d*d        # 1 ² prec 10
   cube_dim   : dim ⟶ dim= [d] d*d*d      # 1 ³ prec 10

   eq_dim     : dim ⟶ dim ⟶ type               # 1 = 2 prec -10role Eq
   assoc      : {d:dim,e:dim,f:dim} d*(e*f)=(d*e)*f
   comm       : {d:dim,e:dim} d*e=e*d
   mult_scalar_right : {d} d*scalar = d        role Simplify
   mult_scalar_left  : {d} scalar*d = d        role Simplify
   mult_inv_right    : {d:dim} d*d⁻ = scalar   role Simplify
   mult_inv_left     : {d:dim} d⁻*d = scalar   role Simplify
   inv_mult   : {d:dim,e:dim} (d*e)⁻ = d⁻*e⁻   role Simplify
   inv_inv    : {d} d⁻⁻ = d                    role Simplify
   

   // the type of quantities of a certain dimension, e.g., 10 s, 100 m ❙
   quantity : dim ⟶ type# $ 1
   eq_quant : {d} $d ⟶ $d ⟶ type               # 2 == 3 prec -10role Eq
   
   // the type of units of a dimension, e.g., second, meter
      units are functions that map real numbers to quantities ❙
   unit : dim ⟶ type = [d] real ⟶ $d
   // takes a real number and a unit and makes the quantity
      e.g., 10'meter❙
   makeQuantity : {d} real ⟶ unit d ⟶ $ d = [d,r,u] u r# 2 ' 3 prec 50
   
   // addition and subtraction quantities ❙
   add_quant : {d} $d ⟶ $d ⟶ $d  # 2 ++ 3
   sub_quant : {d} $d ⟶ $d ⟶ $d  # 2 -- 3
   
   add_quant_same_unit : {d,u: unit d, p, q} p'u ++ q'u == (p + q)'u // role Simplify
   sub_quant_same_unit : {d,u: unit d, p, q} p'u -- q'u == (p - q)'u // role Simplify

   // multiplication and division of dimensions, quantities, and units (should be imported from elsewhere) ❙
   mult_quant : {d,e} $d ⟶ $e ⟶ $(d * e)  # 3 ** 4
   div_quant  : {d,e} $d ⟶ $e ⟶ $(d / e)  # 3 // 4
   mult_unit  : {d,e} unit d ⟶ unit e ⟶ unit(d * e)  # 3 ** 4
              = [d,e,u,v] [r] (r'u) ** (r'v)
   div_unit   : {d,e} unit d ⟶ unit e ⟶ unit(d / e)  # 3 // 4
              = [d,e,u,v] [r] (r'u) // (r'v)

   mult_scalar : {d} real ⟶ $ d ⟶ $ d# 2 @ 3
   multiples_of: {d} $ d ⟶ unit d = [d,q] [r] r @ q# multiples_of 2


theory Dimensions : ur:?LF =
   include ?Quantities
   length : dim
   time   : dim
   mass   : dim
   temperature : dim

   area   : dim= length ²
   volume : dim = length ³
   velocity : dim= length / time
   acceleration : dim = length * time⁻²
   force : dim= mass * acceleration
   pressure : dim= force * length⁻²



theory Prefixes : ur:?LF =
   include ?Dimensions
   // TODO ❙
   milli : {d} unit d ⟶ unit d // = [d,u] [r] (r / 1000) ' u# milli 2
   centi : {d} unit d ⟶ unit d // = [d,u] [r] (r / 100) ' u# centi 2
   deci  : {d} unit d ⟶ unit d // = [d,u] [r] (r / 10) ' u# deci 2

   
theory Units : ur:?LF =
   include ?Dimensions

   meter  : $ length
   second : $ time
   gramm  : $ mass

   meters  : unit length = multiples_of meter
   seconds : unit time   = multiples_of second
   gramms  : unit mass   = multiples_of gramm
   
   kelvin  : $temperature
   kelvins : unit temperature = multiples_of kelvin


theory DerivedUnits : ur:?LF =
   include ?Prefixes
   include ?Units
   
   litre  : $ volume // = (1 ' deci meters) ** (1 ' deci meters) ** (1 ' deci meters)
   litres : unit volume = multiples_of litre


theory CookingUnit : ur:?LF =
   include ?DerivedUnits
   
   tablespoon : $ volume
   teaspoon   : $ volume
   cup        : $ volume
   
   tablespoons : unit volume = multiples_of (15 ' milli litres)
   teaspoons   : unit volume = multiples_of (5 ' milli litres)
   
   cups        : unit volume = multiples_of (250 ' milli litres)


theory TimeUnits : ur:?LF =
   include ?Units
   minutes : unit time = multiples_of (60 ' seconds)
   hours   : unit time = multiples_of (60 ' minutes)


theory TemperatureUnits : ur:?LF =
   include ?Units
   celsius    : unit temperature //  = [r] (r+273+(15/100)) ' kelvins  # 1 °C
   fahrenheit : unit temperature //  = [r] (r-32)*5/9 °C   # 1 °F

namespace http://cds.omdoc.org/examples

import lfrules scala://lf.mmt.kwarc.info/
import stdlit scala://uom.api.mmt.kwarc.info/

/T   a quick, minimal definition of fractional numbers for use in quantities.mmt ❚
theory Real : ur:?LF =
  real: type

  plus: real ⟶ real ⟶ real # 1 + 2 prec 10 
  minus : real ⟶ real ⟶ real  # 1 - 2 prec 10 
  times: real ⟶ real ⟶ real # 1 * 2 prec 15
  div: real ⟶ real ⟶ real # 1 / 2 prec 15
  
  rule lfrules?Realize real stdlit?StandardRat

namespace http://hku.hk/PL

/T The SEDEL type theory (simple type theory with distributive intersection types).
   Formalized with Bruno Oliveira's students during Florian Rabe's March 2019 visit at Hongkong University.
   
   See also https://i.cs.hku.hk/~bruno/papers/nested.pdf and https://i.cs.hku.hk/~bruno/papers/traits.pdf


// define some namespace prefixes❚

import lfx http://gl.mathhub.info/MMT/LFX/Subtyping
import lfrules scala://lf.mmt.kwarc.info/
import stdlit scala://uom.api.mmt.kwarc.info/

theory SEDEL : lfx:?LFSubtyped =
  # Syntactic Categories
  
  /T types and terms of simple type theory❙
  tp : type
  tm : tp ⟶ type# tm 1 prec -5

  # Judgments
  
  ## Equality of terms
  
  equal : {A} tm A ⟶ tm A ⟶ type  # 2  1 3 prec -5role Eq
  refl  : {A,X: tm A} X ≡ A X# refl 2 
  // admissible rule (admissibility proof by logical relation)❙
  cong  : {A,B,X,Y: tm A, F: tm A ⟶ tm B} X ≡ A Y ⟶ (F X) ≡ B (F Y)

  ## Subtyping
  sbt : tp ⟶ tp ⟶ type# 1 < 2 prec -5
  spt : tp ⟶ tp ⟶ type= [A,B] B < A# 1 > 2 prec -5
  
  /T proof irrelevance for subtyping proofs❙
  rule lfrules?TermIrrelevanceRule sbt

  st_refl: {A} A < A
  st_trans: {A,B,C} A < B ⟶ B < C ⟶ A < C

  /T embed SEDEL subtyping into LF subtyping❙
  st_shallow : {A,B} A < B ⟶ tm A <* tm B

  ## Relationship between Equality and Subtyping

  /T equality depends on the type at which terms are compared.
     Equality is preserved when going to larger types.
     But not necessarily the other way round, e.g., all terms are equal at unit type.❙ 
  // TODO: this should type-check❙
  // equal_st : {A,B,s:tm A, t: tm A} A < B ⟶ s ≡ A t ⟶ s ≡ B t❙  
  
  # Syntax

  ## Function Types
  
  fun : tp ⟶ tp ⟶ tp# 1  2
  fun_st : {A,B,C,D} A > C ⟶ B < D ⟶ A → B < C → D
  lambda : {A,B} (tm A ⟶ tm B) ⟶ tm (A → B)# λ 3
  apply : {A,B} tm (A → B) ⟶ tm A ⟶ tm B # 3 @ 4 prec 10
  
  beta : {A,B, F: tm A ⟶ tm B, a} (λ [x] F x) @ a ≡ B (F a) role Simplify# beta 3 4
  cong_apply : {A,B,F: tm (A → B), G, X, Y}
                 (F ≡ (A → B) G) ⟶ X ≡ A Y ⟶ (F @ X) ≡ B (G@Y)
  cong_lambda : {A,B,F: tm A ⟶ tm B,G} ({x} (F x) ≡ B (G x)) ⟶ (λ F) ≡ (A → B) (λ G)

  ## Top type

  /T The top type can be seen as the common supertype of all types, the unit type, and the neutral element of intersection.❙
  
  top : tp# 
  unit : tm ⊤
  st_top : {A} A < ⊤
  eq_top: {x: tm ⊤} x ≡ ⊤ unit

  ## Bottom type
  
  bottom : tp# 
  st_bottom: {A} ⊥ < A
  
  ## Intersection types
  
  inter : tp ⟶ tp ⟶ tp# 1 & 2 prec 10
  inter_st_left  : {A,B} A & B < A
  inter_st_right : {A,B} A & B < B
  inter_glb : {A,B,C} C < A ⟶ C < B ⟶ C < A & B
  
  disjoint: tp ⟶ tp ⟶ type# 1 * 2
  rule lfrules?TermIrrelevanceRule disjoint

  disjointIntro: {A,B} ({C} C > A ⟶ C > B ⟶ C > ⊤) ⟶ A * B
  disjointElim : {A,B} A * B ⟶ {C} C > A ⟶ C > B ⟶ C > ⊤
  
  // TODO: these definitions should type-check❙
  inter_left  : {A,B} tm A & B ⟶ tm A// = [A,B,x] x
  inter_right : {A,B} tm A & B ⟶ tm B// = [A,B,x] x
  inter_in    : {A,B} {a:tm A} {b: tm B} A * B ⟶ tm A & B# 3 ,, 4 %I5
  // TODO: this must solve the proof term (which is in the context) as an implicit argument❙
  // cong_inter_in : {A,B} A * B ⟶ {a1,a2: tm A, b1,b2: tm B}
                  a1 ≡ A a2 ⟶ b1 ≡ B b2 ⟶ (a1 ,,h b1) ≡ (A & B) (a2 ,, b2)❙ 
  
  /T Distributivity is natural but makes it harder to devise algorithms for subtyping.❙
  st_distrib: {A,B,C} (A → B) & (A → C) < A → (B & C)
  st_distrib_0 : {A} ⊤ < (A → ⊤)

  top_arrow : ⊤ < (⊤ → ⊤)= st_distrib_0 ⊤
  
  ## Literals

  nat  : tp
  zero : tm nat
  succ : tm nat ⟶ tm nat

  /T import lexing and computation rules for literals❙ 
  
  rule lfrules?Realize (tm nat) stdlit?StandardNat
  rule lfrules?Realize zero stdlit?Arithmetic/Zero
  rule lfrules?Realize succ stdlit?Arithmetic/Succ

  # Testing
  
  identity : {A} tm A → A  = [A] λ [x] x# id 1
  compose  : {A,B,C} tm A → B ⟶ tm B → C ⟶ tm A → C
           = [A,B,C,f,g] λ[x] g @ (f @ x)
    
  test: (id nat) @ (succ 1) ≡ nat 2= beta ([x] x) 2




  
  
namespace http://cds.omdoc.org/examples

theory FlexaryConnectives : ur:?LFS =
  include ?PL
  
  flexand  : {n} prop^n ⟶ prop#  2
  flexandI : {n} {a: prop^n} ⟨' ⊦ a..i | i:n '⟩ ⟶ ⊦ ⋀ a
  flexandE : {n} {a: prop^n} ⊦ ⋀ a ⟶ {i} DED (succ i) LEQ n ⟶ ⊦ a..i
  
  flexor   : {n} prop^n ⟶ prop#  2
  flexorI  : {n} {a: prop^n} {i} DED (succ i) LEQ n ⟶ ⊦ a..i ⟶ ⊦ ⋁ a
  flexorE  : {n} {a: prop^n} {C} ⊦ ⋁ a ⟶ ⟨' ⊦ a..i ⟶ ⊦ C |i:n '⟩ ⟶ ⊦ C
  
  fleximp  : {n} prop^n ⟶ prop ⟶ prop# 2 ⇒* 3 prec 10
  fleximpI : {n} {a: prop^n, b} (⟨' ⊦ a..i|i:n '⟩ ⟶ ⊦ b) ⟶ ⊦ a ⇒* b
  fleximpE : {n} {a: prop^n, b} ⊦ a ⇒* b ⟶ ⟨' ⊦ a..i|i:n '⟩ ⟶ ⊦ b



theory FlexaryQuantifiers : ur:?LFS =
  include ?FOL

  flexforall : {n} (term^n ⟶ prop) ⟶ prop# ∀* 2
  flexforallI: {n, F: term^n ⟶ prop} ({x:term^n} ⊦ F x) ⟶ ⊦ ∀* [x] F x
  flexforallE: {n, F: term^n ⟶ prop} {x:term^n} ⊦ (∀* [x] F x) ⟶ ⊦ F x

  flexexists : {n} (term^n ⟶ prop) ⟶ prop# ∃* 2
  flexexistsI: {n, F: term^n ⟶ prop} {x:term^n} ⊦ F x ⟶ ⊦ ∃* [x] F x
  flexexistsE: {n, F: term^n ⟶ prop,C} ({x:term^n} ⊦ (∃* [x] F x) ⟶ ⊦ C) ⟶ ⊦ C

namespace http://cds.omdoc.org/examples

//   a simple language for set theory
     This primarily exemplifies advanced notations for parsing and presentation. ❚

theory Sets : http://cds.omdoc.org/urtheories?LF =
  set   : type
  prop  : type
  in    : set ⟶ set ⟶ prop # 1  2 prec 75  role Type
  equal : set ⟶ set ⟶ prop
  // No printable characters are reserved. Here = is used as a delimiter.  # 1 = 2 prec 50
  ded   : prop ⟶ type      # ded 1 prec 0

  // Elem A yields a for elements of the set A.
     Its notation is chosen such that variable attributions can be parsed and presented as x ‍∈ A instead of x : Elem A.❙
  Elem : set ⟶ type       # Elem 1 prec 70

  // The following declaration lifts equal to the types Elem A.
     For parsing (#) it needs a different notation (==); for presentation (##) we can reuse =.❙
  elemequal : {A} Elem A ⟶ Elem A ⟶ prop   # 2 == 3 prec 50  
                                          //  This notation for presentation is 2-dimensional: _ yields a subscript and %I marks an implicit (hidable) argument. 
                                          ## 2 = _ %I1 3 prec 50

  // A universal quantifier over all elements of a given set.
     Using Elem A, the relativization can be expressed in the type system.❙
  forall : {A} (Elem A ⟶ prop) ⟶ prop 
         //  The notation uses V2T for an attributed variable (x ‍∈ A) and -3 for the scope.
             Thus, forall is a binder as far as the MMT notation system is concerned.
             The type system considers it as a higher-order constant of LF. The LF plugin for MMT configures the conversion between the two. 
         #  V2T . -3 prec -1

  empty     : set        #  
         
  // Several set operators use {}-based notations and are binders.
     MMT can handle that.
     However, we have to use ; instead of : for replacement because the delimiter scheme { : } is already used for the Pi symbol of LF.
     Because the notations are left- and right-closed, we can give them very low precedences, which has the effect that they act like brackets.❙
  compr : {A} (Elem A ⟶ prop) ⟶ set       # { V2T | -3 } prec -100004
  repl  : {A}{B} (Elem A ⟶ Elem B) ⟶ set  # { -4 ; V3T } prec -100006

  union    : set ⟶ set ⟶ set          # 1  2 prec 120
  inter    : set ⟶ set ⟶ set          # 1  2 prec 120
  // The big operators for union and intersection are binders with 2-dimensional notations.
     In the __ produces underscripts.❙
  bigunion : {A} (Elem A ⟶ set) ⟶ set #  V2T . -3 prec 60   ##  __ V2T -3 prec 5
  biginter : {A} (Elem A ⟶ set) ⟶ set #  V2T . -3 prec 60   ##  __ V2T -3 prec 5
  
  fun  : set ⟶ set ⟶ set # 1  2 prec 120  //  ^ produces superscripts.  ## 2 ^ 1 
  lam  : {A}{B} (Elem A ⟶ Elem B) ⟶ Elem (fun A B)        # λ 3
  app  : {A}{B} Elem (fun A B) ⟶ Elem A ⟶ Elem B          # 3 @ 4 prec 120
  
  prod : set ⟶ set ⟶ set # 1 × 2 prec 120
  pair : {A}{B} Elem A ⟶ Elem B ⟶ Elem (A × B)
       //  We can use () in notations as well. But the precedence has to below the precedence of the built-in notation for bracketed expressions.  
       # ( 3 , 4 ) prec -1000000001
  // The two projection use, e.g., ._1 for parsing and subscripts for presentation. %D1 yields 1 as a delimiter (instead of an argument marker). ❙
  pi1  : {A}{B} Elem (A × B) ⟶ Elem A # 3 ._1 prec 200  ## 3 _ %D1 prec 200
  pi2  : {A}{B} Elem (A × B) ⟶ Elem B # 3 ._2 prec 201  ## 3 _ %D2 prec 200

  cardinality : set ⟶ set   # | 1 | prec -100000 
  
  // Some example expressions that use the notations. ❙
  
  distributive : {A}{F: Elem A ⟶ set} ded A ∩ ⋃ x ∈ A. (F x) = ⋃ x. A ∩ (F x)
  pairs        : {A} ded {x ∈ A × A | x._1 == x._2} = {(x,x) ; x ∈ A} 
  sizes        : {A} (ded |{f∈A⇒A|∀x∈A.f@x==x}|=|∅⇒∅|)

namespace http://cds.omdoc.org/examples

//   polymorphic equality (essentially identity types) ❚
theory Equality : http://cds.omdoc.org/urtheories?PLF =
  equal : {a:type} a ⟶ a ⟶ type# 2 = 3 prec 50
  refl  : {a,x:a} x = x   # refl 2
  cong  : {a,b,x,y} x = y ⟶ {f: a ⟶ b} (f x) = (f y)# cong 5 6
  cast  : {a: type, A: a ⟶ type, x:a, y:a} x = y ⟶ A x ⟶ A y

  sym   : {a,x:a,y} x = y ⟶ y = x
        = [a,x,y][p] cast a ([u] u = x) x y p (refl x)
  trans : {a,x:a,y,z} x = y ⟶ y = z ⟶ x = z
        = [a,x,y,z,p,q] cast a ([u] x = u) y z q p


//   polymorphic lists ❚
 theory Lists : http://cds.omdoc.org/urtheories?PLF =
  include ?Equality
  list  : type ⟶ type
  nil   : {a} list a # nil %I1
  cons  : {a} a ⟶ list a ⟶ list a # 2 , 3 prec 75

  append : {a} list a ⟶ list a ⟶ list a # 2 + 3 prec 75
  append_nil  : {a, m: list a} nil + m = m
  append_cons : {a, x: a, l: list a, m: list a} (x, l) + m = x , (l + m)

namespace http://cds.omdoc.org/examples

theory DepSumChurch : http://cds.omdoc.org/urtheories?LF =
  tp    : type 
  tm    : tp ⟶ type  # tm 1 prec -5
  equal : {A} tm A ⟶ tm A ⟶ type  # 2 = 3   role Eq

  Sigma  : {A} (tm A ⟶ tp) ⟶ tp                                       # Σ 2 
  pair   : {A, B: tm A ⟶ tp} {x} tm (B x) ⟶ tm Σ [x] B x              # pair 3 4
  pi1    : {A, B: tm A ⟶ tp} tm (Σ [x] B x) ⟶ tm A                    # pi1 3 
  pi2    : {A, B: tm A ⟶ tp} {u:tm (Σ [x] B x)} tm (B (pi1 u))        # pi2 3 
  prod   : tp ⟶ tp ⟶ tp 
         = [A,B] Σ [x: tm A] B   
         # 1 × 2 prec 3

  conv_pair : {A, B: tm A ⟶ tp, u: tm Σ [x] B x} u = pair (pi1 u) (pi2 u)     
  conv_pi1  : {A, B: tm A ⟶ tp, X, Y: tm (B X)} pi1 (pair A B X Y) = X         role Simplify 
  // Note that conv_pi2 only type-checks because conv_pi1 is used as a simplification rule. ❙  
  conv_pi2  : {A, B: tm A ⟶ tp, X, Y: tm (B X)} pi2 (pair A B X Y) = Y         role Simplify


theory DepSumLF : http://cds.omdoc.org/urtheories?DHOL =
    Sigma : {A:type} (A ⟶ type) ⟶ type  # Σ 2 
    pair : {A : type, B: A ⟶ type, a : A } B a ⟶ Σ B  # pair 3 4 
    pi1 : {A : type, B: A ⟶ type} Σ B ⟶ A  # pi1 3 
    pi2 : {A : type, B: A ⟶ type} {p : Σ B} B (pi1 p)  # pi2 3

    conv_pair : {A: type, B: A ⟶ type, u: Σ B} DED u EQ (pair (pi1 u) (pi2 u)) 
    conv_pi1 : {A : type, B: A ⟶ type}{a : A, b: B a} DED (pi1 (pair A B a b)) EQ a  role Simplify 
  // Note that conv_pi2 only type-checks because conv_pi1 is used as a simplification rule. ❙
    conv_pi2 : {A : type, B: A ⟶ type}{a : A, b: B a} DED (pi2 (pair A B a b)) EQ b  role Simplify 

/T   This file contains the general structure of the MMT tutorial given at CICM 2016.❚


/T   A namespace declaration defines the root URI of the following content.❚
namespace http://cds.omdoc.org/examples/tutorial

document SFOL 

/T   A theory defines a language. It may optionally use a meta-theory, which is given by its URI.❚
ref ?FOL 

/T   We can already use our logic as the meta-theory of a theory.
     To refer to FOL, we use its URI, which is of the form NAMESPACE?THEORYNAME.


/T   A Semigroup consists of ...❚
ref ?Semigroup 

  
/T   Now we define the proof theory of LF using natural ⊢uction proof rules.
     It is practical to do this in a separate theory that includes the syntax above.
        
     
ref ?NatDed 

/T   The rules declared so far only yield intuitionistic first-order logic. To get to classical logic,
we can use the modular approach and extend NatDed by the law of excluded middle: ❚
ref ?ClassicalSFOL 


document AlgebraicHierarchy 

/T   Exemplary, we can now built the usual hierarchy of algebraic theories in a modualar way, starting again with
	semigroups: ❚
ref ?Semigroup 

/T   Monoids just extend Semigroups: ❚
ref ?Monoid 

/T   A Monoid happens to be a preorder - a fact, that we can express using Views. A view is a morphism
		between two theories, that maps each declaration of the domain to a valid expression
		over the symbols in the codomain such, that typing judgments are preserved. ❚
		
/T   First, a theory of preorders: ❚
ref ?PreOrder 

/T   To show that monoids are preorders, we have to map each axiom of a preorder to a provable
			statement in the theory of monoids, i.e. we need a view preorder ⟶ monoid, like so: ❚
ref ?MonoidAsPreorder 

/T   Next, on to groups: ❚
ref ?Group 

/T   For Rings we will need abelian groups in particular, so let's create a theory for "abelian": ❚
ref ?Abelian 

/T   ...and one for abelian groups: ❚
ref ?AbelianGroup 

/T   Now for Rings. Obviously, if we want to implement a theory of rings modularly, we
			want to make use of the fact, that a ring is an additive abelian group with a multiplicative monoid.
			Both theories already exist, but we need them with respect to two different operations - includes
			will not get us there. Instead, we will use MMT structures. Structures behave like includes,
			except that they allow us to slightly modify the imported declarations; in particular we are allowed
			to provide new definitions and notations for the imported symbols: ❚
ref ?Ring 


document LiteralsAndRules 
/T   Next, we will look at different ways to implement RULES by writing a theory for 
			natural numbers ❚
ref ?Nat 

/T   And of course, natural numbers form a monoid, which we can express with a view: ❚
ref ?NatAsMonoid 
//   Comments begin with // and end with the delimiter of the current level.
     
     Comments starting with /T count as content themselves and are, e.g., preserved in the HTML  rendering of a file.
     Therefore, all comments in this file start with /T❚


/T   This file contains a definition of first-order logic in MMT as used in the MMT tutorial given at CICM 2016.❚


/T   A namespace declaration defines the root URI of the following content.❚
namespace http://cds.omdoc.org/examples/tutorial

/T   A theory defines a language. It may optionally use a meta-theory, which is given by its URI.❚
theory FOL : http://cds.omdoc.org/urtheories?PLF =

  /T The simplest declaration in an MMT theory introduces a named symbol.
     Every declaration can have multiple attributes following the name.
     Each attribute is introduced by a special keywork:
       the type      - introduced by ':'.
       the definiens - introduced by '='
       the notation  - introduced by '#'
     If multiple attributes are present, they must be ended with the object delimiter. 


  /T The following declaration introduces the type of FOL propositions.
     Its type is the object 'type', which is defined by LF.❙
  prop  : type 
  
  /T All symbols occuring in an MMT object are cross-linked to their declaration.
     Try hovering or control-clicking on 'type' above❙
  
  /T The following declarations introduce the constructors of propositional logic and their notations.❙
  
  /T ⟶ is used for simple functions. It is part of the notations defined by LF.
     It is right-associative. By double-clicking on ⟶, you can see its arguments.❙
  
  true  : prop                                 
  false : prop                                 
  and   : prop ⟶ prop ⟶ prop   # 1  2 prec 15
  or    : prop ⟶ prop ⟶ prop   # 1  2 prec 15
  impl  : prop ⟶ prop ⟶ prop   # 1  2 prec 10
  not   : prop ⟶ prop          # ¬ 1   prec 20
  /T Note that multiple attributes (here: type and notation) must be separated by ❘.
     Among other things, that allows using :, =, and # as ordinary characters anywhere else.❙

  /T Notations consist of numbers refering to argument positions and arbitrary Unicode strings defining delimiters.
     Optionally, a notation may end in 'prec NUMBER' to define a precedence. Higher precedences bind stronger.
     For example, '1 ∧ 2 prec 15' makes conjunction an infix operator with precedence 15.


  /T As an example for a defined symbol, let us consider the equivalence connective.
     We define it in terms of conjunction and implication.
     The definiens uses [x:prop,y:prop], which is the notation defined for lambda-abstraction in LF.
     The types of the bound variables are infered by MMT - try hovering over them to see the types.

  equiv : prop ⟶ prop ⟶ prop   # 1  2 prec 10
        = [x,y] (x ⇒ y) ∧ (y ⇒ x)
  /T Here three attributes (type, notation, and definition) are present. The order does not matter.❙
  
  /T Now for the first-order aspects.
     We opt for sorted (also called typed) first-order logic, e.g., there may be multiple sorts that we can quantify over separately.❙
  
  /T The following declarations introduce the LF-type of sorts and the LF type of terms of a given sort.❙
 
  sort   : type
  term   : sort ⟶ type # tm 1
  
  /T The point of the latter is as follows: If, e.g., 's:sort' is a sort, then 'tm s' is the type of all terms of sort s❙

  /T The following declaration introduces a symbol for sorted equality.❙
  equal : {s: sort} tm s ⟶ tm s ⟶ prop# 2 = 3 prec 30  role Eq 
  /T Here {s: sort} is the Pi-binder of LF for dependent function spaces.
       Thus, equal takes a sort as its first argument and then 2 terms of that sort.❙
  /T In the notation for equal, the first argument - the sort - is not mentioned.
     That makes the sort an implicit argument that is infered by MMT.

  
  /T The types of the quantifiers use LF's higher-order abstract syntax:
     'tm s ⟶ prop' can be used as the type of proposition with a free variables of type 'tm s'.
     The sort is an implicit argument again, and the type of sort is infered by MMT.

  forall : {s} (tm s ⟶ prop) ⟶ prop#  2
  exists : {s} (tm s ⟶ prop) ⟶ prop#  2
  
  /T Finally, we need to be able to talk about the truth of propositions.
     For that, we introduce a Curry-Howard style judgment: The LF-type '⊢ P' is the type of proofs of the proposition 'P'.

  proof : prop ⟶ type #  1 prec 0
         role Judgment
  /T It's practical to give ⊢ a very low precedence to avoid brackets later on.❙
  
  /T The 'role Judgment' is an attribute introduced by the LF plugin (which tells MMT to be loaded automatically whenever LF is used).
     By annotation the symbol 'proof' in this way, the plugin can add some LF-specific language support, in particular, it can generate appropriate default notations.

 


  
/T   Now we define the proof theory of LF using natural deduction proof rules.
     It is practical to do this in a separate theory that includes the syntax above.
        
theory NatDed : http://cds.omdoc.org/urtheories?LF =

  /T 'include THEORY' includes another theory.
     When refering to a theory, we do not actually have to give the absolute URI.
     Below the relative URI '?FOL' is resolved relative to the current namespace and yields http://cds.omdoc.org/examples/tutorial?FOL.

  include ?FOL 

  /T Some FOL proof rules talk about contradictioins.
     A FOL theory is contradictory if we can derive any formula. That can be captured by the LF type '{a: prop} ⊢ a'. If this type is non-empty, a theory is inconsistent.
     We introduce an abbreviation for it:❙
  contra : type  = {a} ⊢ a # 

  trueI : ⊢ true

  falseE : ⊢ false ⟶ ↯
  
  andI  : {A,B} ⊢ A ⟶ ⊢ B ⟶ ⊢ A ∧ B   
  andEl : {A,B} ⊢ A ∧ B ⟶ ⊢ A         
  andEr : {A,B} ⊢ A ∧ B ⟶ ⊢ B         

  orIl  : {A,B} ⊢ A ⟶ ⊢ A ∨ B         
  orIr  : {A,B} ⊢ B ⟶ ⊢ A ∨ B         
  orE   : {A,B,C} ⊢ A ∨ B ⟶ (⊢ A ⟶ ⊢ C) ⟶ (⊢ B ⟶ ⊢ C) ⟶ ⊢ C
                                      

  impI  : {A,B} (⊢ A ⟶ ⊢ B) ⟶ ⊢ A ⇒ B 
  impE  : {A,B} ⊢ A ⇒ B ⟶ ⊢ A ⟶ ⊢ B   

  notI  : {A} (⊢ A ⟶ ↯) ⟶ ⊢ ¬ A# notI 2
  notE  : {A} ⊢ ¬ A ⟶ ⊢ A ⟶ ↯  # notE 2 3

  /T Because equivalence is defined, we can derive its rules.
     As usual for Curry-Howard style representations, a derived rule is simply a rule with a definiens.


  equivI : {A,B} (⊢ A ⟶ ⊢ B) ⟶ (⊢ B ⟶ ⊢ A) ⟶ ⊢ A ⇔ B  
         = [A,B,p,q] andI (impI [x] p x) (impI [x] q x)  
         
  equivEl : {A,B} ⊢ A ⇔ B ⟶ ⊢ A ⟶ ⊢ B
          = [A,B,p,a] impE (andEl p) a 
  equivEr : {A,B} ⊢ A ⇔ B ⟶ ⊢ B ⟶ ⊢ A
          = [A,B,p,b] impE (andEr p) b 
          
  forallI  : {s, A: tm s ⟶ prop} ({x} ⊢ (A x)) ⟶ ⊢ ∀ A  # allI 3
  forallE  : {s, A: tm s ⟶ prop} ⊢ (∀ A) ⟶ {x} ⊢ (A x)  # allE 3 4

  existsI  : {s, A: tm s ⟶ prop} {c} ⊢ (A c) ⟶ ⊢ ∃ [x] (A x) # exI 3 4
  existsE  : {s, A: tm s ⟶ prop, C} ⊢ (∃ A) ⟶ ({x} ⊢ (A x) ⟶ ⊢ C) ⟶ ⊢ C  # exE 4 5

  /T The rules for equality consist of the equivalence rules at every sort ...❙
  refl     : {s,x: tm s} ⊢ x = x  # refl 2 
  sym      : {s,x: tm s,y} ⊢ x = y ⟶ ⊢ y = x# sym 4
  trans    : {s,x: tm s,y,z} ⊢ x = y ⟶ ⊢ y = z ⟶ ⊢ x = z # trans 5 6
  /T ... and congruence rules for substituting a subterm x with y in any term T or formula F.❙
  congTerm : {s,t, T: tm s ⟶ tm t}{x,y} ⊢ x = y ⟶ ⊢ (T x) = (T y)# congTerm 3 6
  congForm : {s,   F: tm s ⟶ prop}{x,y} ⊢ x = y ⟶ ⊢ (F x) ⟶ ⊢ (F y)# congForm 2 5 6


/T   The rules declared so far only yield intuitionistic first-order logic. To get to classical logic,
we can use the modular approach and extend NatDed by the law of excluded middle: ❚
theory ClassicalSFOL : ur:?LF =
	include ?NatDed 
	
	TND : {A} ⊢ A ∨ ¬ A  # TND 1 

namespace http://cds.omdoc.org/examples/tutorial

/T   A Semigroup consists of ...❚
theory Semigroup : ?NatDed =
   /T ... a sort for the universe ...❙   
   u : sort
   /T ... a binary function on the universe, written as infix ∘ ...❙
   comp : tm u ⟶ tm u ⟶ tm u # 1  2 prec 40
   /T ...such that ∘ is associative.❙
   assoc : ⊢  ∀[x]∀[y]∀[z] (x ∘ y) ∘ z = x ∘ (y ∘ z)
   
   /T We prove a few abbreviations that come in handy when doing proofs:❙
   assocLeftToRight: {x,y,z} ⊢ (x ∘ y) ∘ z = x ∘ (y ∘ z)= [x,y,z] allE (allE (allE assoc x) y) z # assocLR %I1 %I2 %I3
   assocRightToLeft: {x,y,z} ⊢ x ∘ (y ∘ z) = (x ∘ y) ∘ z= [x,y,z] sym assocLR # assocRL %I1 %I2 %I3

 
theory Monoid : ?NatDed =
	include ?Semigroup 
	
  // metadata can be attributed both to a theory ... ❙
  @_description s
	// ... and to constants ... ❙
	unit : tm u  # e  @_description  
	// ... any symbol can be used as a metadata key, several @_XXX keys are predefined❙
	
	unit_axiom : ⊢ ∀[x] x ∘ e = x @_description  

	                                   
theory PreOrder : ?NatDed =
	o : sort 
	order : tm o ⟶ tm o ⟶ prop  # 1  2 prec 50 
	reflexivity : {x} ⊢ x ≤ x 
	transitivity : {x,y,z} ⊢ x ≤ y ⟶ ⊢ y ≤ z ⟶ ⊢ x ≤ z 
	
	// We prove the ternary case of transitivity by chaining transitivity twice.❙
	transitivity3: {w,x,y,z} ⊢ w ≤ x ⟶ ⊢ x ≤ y ⟶ ⊢ y ≤ z ⟶ ⊢ w ≤ z
	      = [w,x,y,z,p,q,r] transitivity (transitivity p q) r


	
view MonoidAsPreorder : ?PreOrder  ?Monoid =
	/T Assignments in views are of the form NAME = EXPRESSION. First, the universes: ❙
	o = u 
	/T Now for the order itself, which is defined by a ≤ b ⇔ ∃x a∘x=b. Thus: ❙
	order = [x,y] (∃[z] x ∘ z = y) 
	/T The target statement for reflexivity translates as ${x} ⊢ ∃[z] x ∘ z = x$, which
		we now need to prove for monoids: ❙
	reflexivity = [x] exI e (allE unit_axiom x)
	/T The target statement for transitivity is ${x,y,z} ⊢ (∃[a] x ∘ a = y) ⟶ ⊢ (∃[b] y ∘ b = z) ⟶ ⊢ ∃[c] x ∘ c = z$ where the proof has to extract witness a with proof pa from p and b and qb from q and then supply the witness c as a∘b along with its proof:❙
	transitivity = [x,y,z,p,q] exE p [a,pa] exE q [b,qb] exI (a ∘ b) trans assocRL trans (congTerm ([k]k∘b) pa) qb

	
theory Abelian : ?NatDed =
	include ?Semigroup 

	commutative : ⊢ ∀[x] ∀[y] x ∘ y = y ∘ x 

	
theory Group : ?NatDed =
	include ?Monoid 
	
	inverse : tm u ⟶ tm u  # 1 ⁻¹   
	/T jsuperminus jsuper1	❙
	
	inverse_axiom : ⊢ ∀[x] x ∘ (x ⁻¹ ) = e 


theory AbelianGroup : ?NatDed =
	include ?Group 
	include ?Abelian 

	
theory Ring : ?NatDed =
	/T We will add two structures, one for addition and one for multiplication. ❙
	/T Addition forms an abelian group, hence we will use that theory for our structure. ❙
	/T In the structure, we first give the universe u a new ALIAS R. This way, we don't
		have to refer to the universe of our Ring with add/u all the time. ❙
	/T Afterwards, we provide new notations for the other symbols. Note, that none of the symbols
			we "modify" are declared directly in the theory we're including (i.e. AbelianGroup).
			Structures can modify along includes without problems. ❙
	structure add : ?AbelianGroup =
		u @ R 
		comp # 1 + 2 prec 40 
		unit # O 
		inverse # - 1 
	
	/T We can now add a DEFINITION to Multiplication/u, making it equal to R=Addition/u. 
		That way, both + and ⋅ are defined on the SAME
		universe (i.e. R), while being two separate operations nonetheless (as opposed to when
		using plain includes): ❙
	structure mult : ?Monoid =
		u = R 
		comp # 1  2 prec 45 
		unit # I 
	
	/T Alternatively we could have defined mult/u directly as add/u
		
	/T Finally, we can use the symbols in our structures jointly in distributivity: ❙
		
	distributive : ⊢ ∀[a]∀[b]∀[c] a ⋅ (b + c) = a ⋅ b + a ⋅ c 

namespace http://cds.omdoc.org/examples/tutorial

import rules scala://tutorial.examples.mmt.kwarc.info

theory Nat : ?NatDed =
	/T We start with a sort for the natural numbers and an abbreviation ℕ for the terms
		of that sort - i.e. the type of actual numbers, which we will populate with literals: ❙
	Nat : sort 
	 = tm Nat 
	
	/T The literals are provided by a RealizedType rule written in Scala in 
		scala_realizations/info/kwarc/mmt/examples/tutorial/Literals.scala
	  These rules are special constants declared by the "rule" keyword followed by the classname: ❙
	rule rules?NatLiterals 
	/T The MMT build system includes a target for building these Scala files - the command is "build MMT/examples scala-bin" ❙

	/T The rule NatLiterals introduces MMT literals for all natural numbers as well as a lexing rule for them.
	   To see whether it works, let's define the constant "zero" as the literal 0: ❙
	zero = 0 
	
	/T In addition to RealizedType rules, there are also RealizedOperator rules, which allow us
		to associate a function on literals declared in MMT with a corresponding implementation 
		in Scala. We can use this to implement the successor function: ❙
	S : ℕ ⟶ ℕ 
	rule rules?Succ 

	/T Succ is implemented in such a way that it can be inverted, which MMT will use for unification, when working with terms that contain both literals and variables: ❙

	/T MMT will now simplify every instance of S being applied to literals to the actual
		computation result. We can test this, by proving that the successor
		of 17 is 18 by reflexivity of equality alone: ❙
	succ_test : ⊢ S 17 = 18  = refl 18 
	
	/T Now for the same thing with addition: ❙
	plus : ℕ ⟶ ℕ ⟶ ℕ  # 1 + 2 prec 40 
	rule rules?Plus 
	/T We can again test, whether this works by proving an equality with refl: ❙
	plus_test : ⊢ 5 + 5 = 10  = refl 10 
	
	/T We use Scala to implement computations on literals.
	   Additionally, we need symbolic rewrite rules for working with other expressions.
	   The LF plugin includes a ChangeListener that automatically generates rewrite rules from certain constants.
	   To do so, we add the role Simplify to the constants.
	   We must have previously added roles Judgment and Eq to ⊢ and =, respectively.❙
	plus_def1 : {x} ⊢ x + zero = x  # plus_def1 1  role Simplify 
	plus_def1b : {x} ⊢ zero + x = x  role Simplify 
	plus_def2 : {x,y} ⊢ S x + y = S (x + y)  role Simplify 
	plus_def2b : {x,y} ⊢ x + S y = S (x + y)  role Simplify 
	/T The generate rules will make MMT rewrite the left to the right side of the equality during type-checking. ❙
	
	/T We also add associativity (omitting the proof), which we need in the view below.❙
  plus_assoc : {x,y,z} ⊢ (x + y) + z = x + (y + z)  # plus_assoc 1 2 3 

	
view NatAsMonoid : ?Monoid  ?Nat =
	u = Nat 
	comp = plus 
	unit = zero 
	assoc = allI ([x] allI ([y] allI (plus_assoc x y))) 
	unit_axiom = allI ([x] plus_def1 x) 

namespace http://cds.omdoc.org/urtheories

import rules scala://cf.mmt.kwarc.info

theory CF =
   include ?PLF

   constant instance # instance 1
   new    # new 1
   rule rules?NewInstance
   field    # 1 . 2

   
   sequence # var V1; in 2;
   rule rules?Sequence

   None: type
   none: None
  
   assign # 1 = 2
   rule rules?Assignment
   rule rules?AssignmentTerm

namespace http://cds.omdoc.org/urtheories

import meta http://cds.omdoc.org/mmt

theory Dedukti =
   include ?PLF
   rewriteType: type ⟶ type ⟶ type # 1 ---> 2 role Eq
   rewriteTerm: {a: type} a ⟶ a ⟶ type  # 1 --> 2 role Eq
                                   
namespace http://cds.omdoc.org/urtheories

import rules scala://quotation.mmt.kwarc.info

/T   higher-order logic with quotation and evaluation, mostly following Bill Farmer's work ❚
theory HOLQE : ?LF =
   # Higher-order logic
  
   ## Types

   /T the LF-type representing HOL types ❙ 
   tp  : type
   /T function types ❙ 
   fun : tp ⟶ tp ⟶ tp # 1  2 prec 20

   /T Normally we represent object language variables using LF variables, in which case the following is redundant.
      But Farmer's language follows the traditional style of assuming an infinite supply of variables at every type.
      It is critical to capture this in the representation because he allows quoting terms with free variables.❙
   /T the type of variables at a given HOL type❙
   Var : tp ⟶ type
   /T the constructor for concrete variables %x:a at a given HOL type where x is any identifier that is parsed as a closed term
      Most of the time, we do not need this because we can use LF-variables v:Var a as meta-variables that range over HOL variables at type a.❙ 
   var # % L1T prec 200
   /T the typing rule (%x:a):Var a for concrete variables cannot be expressed in LF, so we implement an MMT rule❙ 
   rule rules?ConcreteVariable
   
   ## Terms
   
   /T the LF-type representing HOL terms of a given HOL type ❙  
   tm : tp ⟶ type # tm 1 prec -1
   /T all variables are terms of their respective type ❙ 
   tvar : {a} Var a ⟶ tm a# tvar 2## 2 prec 100
   /T λ-abstraction (contrary to typical LF-encodings, we bind explicit variables that have to be injected into terms using tvar ❙ 
   lam : {a, b} (Var a ⟶ tm b) ⟶ tm a ⇒ b # λ 3
   /T application ❙ 
   app : {a, b} tm a ⇒ b ⟶ tm a ⟶ tm b # 3 @ 4 prec 20
   /T undefined terms (not needed here, but probably needed later on when evaluating quotations of ill-typed terms❙ 
   undefined : {a} tm a#  1

   /T booleans, connectives, and proofs❙ 
   bool : tp
   equal : {a} tm a ⟶ tm a ⟶ tm bool  # 2 = 3 prec 10

   ded  : tm bool ⟶ type #  1 prec -1
   
   # Quotation 
   
   /T We add HOL types that reify HOL concepts❙ 

   ## Quoting Terms 

   /T We add a type holding quotations of HOL terms. All terms may be quoted, including ill-typed ones.
      Effectively, this amounts to having a type that represents the untype λ-calculus inside a typed λ-calculus.❙ 

   ### Syntax    
      
   /T the type of quoted terms❙
   qtp  : tp  # ε
   /T quoted variables❙
   qvar : {a} Var a ⟶ tm ε# qvar 2 prec 100## qvar 2 prec 100 
   /T quoted λ-abstractions❙
   qlam : {a} Var a ⟶ tm ε ⟶ tm ε  # qlam 2 . 3 prec 150
   /T quoted applications❙
   qapp : tm ε ⟶ tm ε ⟶ tm ε  # qapp 1 2 prec 20
   /T quoted quotations❙
   qquote: tm ε ⟶ tm ε

   /T Finally, we add a meta-level operation that turns a term into the corresponding quotation.
      We may think of it as having type ${a}tm a ⟶ tm ε$ except. However, quotation may not be subject to congruence and therefore cannot have an LF type.❙   
   quote #  1   prec 10
   /T the rule that eliminates occurrences of quote by constructing the corresponding term of type $tm ε$
      HOL variables in the argument are quoted using $qvar$, LF variables remain, which gives rise to quasi-quotation.❙ 
   rule rules?QuoteTerm

   ### Semantics

   /T the predicate expressing that a term is the quotation of a term of a given types.❙
   oftype     : tm ε ⟶ tp ⟶ tm bool# 1 $ 2 prec 5
   /T typing rule for quoted variables❙
   oftype_var : {a,v: Var a} ⊦ qvar v $ a
   /T typing rule for quoted λ-abstractions❙
   oftype_lam : {a,b,v:Var a,E} ⊦ E $ b ⟶ ⊦ qlam v.E $ a ⇒ b
   /T typing rule for quoted applications❙
   oftype_app : {a,b,F,E} ⊦ F $ a ⇒ b ⟶ ⊦ E $ a ⟶ ⊦ qapp F E $ a ⇒ b
   /T typing rule for quoted quotations❙
   oftype_quote: {E,a} ⊦ E $ a ⟶ ⊦ qquote E $ ε   

   ## Quoting Substitutions 

   /T Expanding on Farmer's work, we also add a type holding HOL substitutions.
      Effectively, this amounts to a language with explicit substitutions.
      Because all variables are always in scope, every substitution maps all variables to terms.❙ 

   ### Syntax
   
   /T the type of substitutions❙
   stp  : tp # sub
   /T the identity substitutions❙
   idsub: tm sub
   /T the substitution that modifies a given substitution in one place❙
   update: {a} tm sub ⟶ Var a ⟶ tm a ⟶ tm sub # 2 + 3  4 prec 50

   /T abbreviation for the substitution that maps one variable❙   
   singlesub: {a} Var a ⟶ tm a ⟶ tm sub # 2  3 prec 51
            = [a,v,t] idsub + v ↦ t

   /T Finally, we add a meta-level operation that turns a substitution into the corresponding quotation.❙   
   subs # ` L1T, ´  prec 10
   /T the rule that eliminates occurrences of subs by constructing the corresponding term of type $tm sub$❙ 
   // rule rules?QuoteSubs❙

   ### Semantics

   /T an auxiliary predicate to reason about inequality of variables❙
   diff : {a,b} Var a ⟶ Var b ⟶ tm bool # 3  4 prec 10 // notation parsing errors not reported correctly? ❙
   
   /T the function that retrieves the map of a variable by a substitution❙
   lookup: {a} tm sub ⟶ Var a ⟶ tm a # 3 ' 2 prec 15
   /T the lookup rule for the identity substitution❙   
   subst_id     : {a,v: Var a} ⊦ v'idsub = (tvar v)
   /T the lookup rule for an update to the needed variables❙   
   subst_update_same : {s,a, v: Var a, E} ⊦ v'(s+v↦E) = E
   /T the lookup rule for an update to some other variable❙   
   subst_update_diff : {s,a,b, v: Var a, w: Var b, E} ⊦ v ≠ w ⟶ ⊦ v'(s+w↦E) = v's
   
   # Evaluation
   
   /T Evaluation internalizes the model-theoretical semantics: evaluation takes a term and a substitution (which provides the assignment to the free variables) and returns its interpretation in the model.
   
   Evaluation is only defined for quotations of well-typed terms. Because the type of a quotation is not stored in the quotation,
   * evaluation takes a HOL-type as an additional argument,
   * evaluation rules take typing assumptions.❙
   
   /T the evaluation operator❙
   eval     : {a} tm ε ⟶ tm sub ⟶ tm a  #  2 $ 1  3 prec -5  ##  2 $ 1  ^ 3 prec -5
   /T the evaluation rule for variables: apply the assignment❙
   eval_var : {a, v: Var a, s} ⊦ (⟦qvar v $ a⟧s) = v's
   /T the evaluation rule for λ-abstractions qlam v.E: build the function that maps x to the evaluation of E under the assignment of v to x❙
   eval_fun : {a, b, v: Var a, E, s} ⊦ E $ b ⟶ ⊦ (⟦qlam v.E $ a ⇒ b⟧s) = λ[x](⟦E $ b⟧ s + v ↦ tvar x)
   /T the evaluation rule for applications: straightforward❙
   eval_app : {a,b, F, X, s} ⊦ F $ a ⇒ b  ⟶  ⊦ X $ a  ⟶  ⊦ (⟦qapp F X $ b⟧s) = (⟦F $ a ⇒ b⟧s) @ ⟦X $ a⟧s
   /T the evaluation rule for quotations: evaluation cancels quotation❙
   eval_quote : {X, s} ⊦ X $ ε  ⟶  ⊦ (⟦qquote X $ ε⟧s) = X

  
/T Now we formalize two challenge problems posed by Farmer❚
 
theory ExcludedMiddle : ?HOLQE =
  not : tm bool ⟶ tm bool# ¬ 1
  or  : tm bool ⟶ tm bool ⟶ tm bool# 1  2
  em  : {f,s} ⊦ f $ bool ⟶ ⊦ (⟦f$bool⟧s) ∨ ¬ ⟦f$bool⟧s 


theory PolyDiff : ?HOLQE =
  /T real numbers and derivatives❙
  R: tp
  derivative : tm R ⇒ R ⟶ tm R ⇒ R
  
  /T a transformer that computes the derivative of a polynomial and its meaning formula❙
  ispolyin: tm ε ⟶ Var R ⟶ tm bool
  polyderiv: tm ε ⟶ Var R ⟶ tm ε
  meaning: {v, p} ⊦ ispolyin p v ⟶ ⊦ derivative (λ[x] ⟦p $ R⟧v ↦ tvar x) = (λ[x] ⟦polyderiv p v $ R⟧v ↦ tvar x) 

namespace http://cds.omdoc.org/urtheories

import rules scala://intersection.mmt.kwarc.info

/T   A representation of intersection types in MMT, following "Towards a Logical Framework with Intersection and Union Types" by Stolze, Liquori, Honsell, Scagnetto.❚

theory Intersection =
   include ?LF
   
   /T intersection type❙
   inter # 1  2
   /T elements of an intersection type❙
   pair #  1 , 2  
   /T projections from an intersection type❙
   project1 # proj1 1 
   project2 # proj2 1 

   rule rules?InterTerm
   rule rules?PairTerm
   rule rules?Projection1Term
   rule rules?Projection2Term
   rule rules?InterTyping
   rule rules?InterEqual

   
theory IntersectionTest : ?Intersection = 
  a: type
  b: type

  /T auto-application ❙
  test : ((a ⟶ b) ∩ a) ⟶ b
       = [x] (proj1 x) (proj2 x)
  
  /T This is a negative test: it should fail with an error that $(a ⟶ b)∩(a ⟶ b)$ is not equal to $(a ⟶ b)∩a$.❙
  // test2 = test test❙

namespace http://cds.omdoc.org/urtheories

import rules scala://lf.mmt.kwarc.info
rule scala://parser.api.mmt.kwarc.info?MMTURILexer

theory Isabelle =
   include ☞http://cds.omdoc.org/mmt?Errors❚
   include ?PLF
   
   prop: type
   ded : prop ⟶ type  #  1 prec 0

   proof_text: type

namespace http://cds.omdoc.org/urtheories

import meta http://cds.omdoc.org/mmt
import rules scala://lf.mmt.kwarc.info

rule scala://parser.api.mmt.kwarc.info?MMTURILexer

theory Typed =
   type
   equality # equality 1 2   role Eq

   oftype # 1 : 2 prec -9997  role Type
   definedas  # 1 := 2 prec -9998  role Def
   withnotation # 1 # 2 prec -9998  role Notation

   
theory Kinded =
   include ?Typed
	 kind

   
theory TypedConstants =
   rule rules?UniverseType
   rule rules?TypeInhabitable


theory KindedConstants =
   rule rules?UniverseKind
   rule rules?KindInhabitable


theory TermsTypesKinds =
   include ☞meta:?Errors
   include ?ModExp
   include ☞meta:?mmt
   include ?Typed
   include ?Kinded
   include ?TypedConstants
   include ?KindedConstants
   rule rules?UnivTerm
   rule rules?TypeAttributionTerm
   rule rules?DropTypeAttribution

   
theory LambdaPi =
   include ?Kinded
   Pi     # { V1T, } 2 prec -10000
   lambda # [ V1T, ] 2 prec -10000
   apply  # 1%w        prec -10
   arrow  # 1         prec  -9990

   
theory LFRules =
   include ?LambdaPi
   rule rules?PiType
   rule rules?PiTerm
   rule rules?ApplyTerm
   rule rules?LambdaTerm
   
   rule rules?Beta
   rule rules?Extensionality
   rule rules?PiCongruence
   rule rules?LambdaCongruence
   // rule rules?NormalizeCurrying❙
   rule rules?FlattenCurrying

   rule rules?Solve
   rule rules?SolveType

   rule rules?TheoryTypeWithLF
   
   rule rules?PiIntroduction
   rule rules?ForwardPiElimination
   rule rules?BackwardPiElimination
   rule rules?PiIrrelevanceRule
   rule rules?LFHOAS


theory LF =
   include ?TermsTypesKinds
   include ?LambdaPi
   include ?LFRules

   
theory ShallowPolymorphism =
   include ?Typed
   
   rule rules?ShallowPolymorphism
   rule rules?PolymorphicApplyTerm

   
theory PLF =
   include ?LF
   include ?ShallowPolymorphism

namespace http://cds.omdoc.org/urtheories

theory LFModulo : ?PLF =
   equality : {A:type} A ⟶ A ⟶ type # 2 = 3 prec -9000role Eq
                                                                              
namespace http://cds.omdoc.org/urtheories

/T LLF_P as introduced by Honsell, Liquori, Maksimovi, Scagnetto in
A logical framework for modeling external evidence, side conditions, and proof irrelevance using monads❚

import rules scala://externals.lf.mmt.kwarc.info
import lfrules scala://lf.mmt.kwarc.info

theory Locks =
   // Lp p a b <T> is the type \mathcal{L}^p_{a,b}[T] from the paper.❙
   locktype # Lp 1 2 3 < 4 > 
   // Lm p a b <t> is the term \mathcal{L}^p_{a,b}[t] from the paper.❙
   lockterm # Lm 1 2 3 < 4 > 
   // U <t> for t:Lp p a b <T> is the term \mathcal{U}^p_{a,b}[t] from the paper.
      U is unary here because p, a, and b can be inferred from t.❙
   unlock # U < 1 >                                            
   
   // Convenience operator to bundle p, a, b into a single object.
   key # K 1 2 3❙

   // The typing rules.❙
   rule rules?InferLockType
   rule rules?InferLockTerm
   rule rules?InferUnlock
   rule rules?TypingLock
   rule rules?EqualityLock
   rule rules?UnlockLock


theory LLFP =
   include ?LF
   include ?Locks


theory CallByValueExample : ?LLFP =
   /T following Section 5.1 of the paper: call-by-value reduction ❙

   /T untyped λ calculus ❙
   term : type
   app : term ⟶ term ⟶ term  # 1 @ 2 prec 50
   lam : (term ⟶ term) ⟶ term # λ 1

   /T natural numbers ❙
   nat : type
   z : nat
   S : nat ⟶ nat
   
   /T free variables using natural numbers❙
   free : nat ⟶ term# ' 1 prec 100

   /T equality judgment and its rules ❙
   eq : term ⟶ term ⟶ type # 1  2  role Judgment
   refl : {M} M ≐ M# refl 1
   symm : {M,N} M ≐ N ⟶ N ≐ M
   trans : {M,N,P} M ≐ N ⟶ N ≐ P ⟶ M ≐ P
   eq_app: {M,N,X,Y} M ≐ N ⟶ X ≐ Y ⟶ M@X ≐ N@Y # eq_app 5 6

   /T We declare a single constant Val for the side condition and one rule that implements it.
      The condition Val N term checks if N:term is an abstraction or a free variable ❙
   Val
   rule rules?ValRule
   
   /T reduction rules using Val condition❙
   betav : {M,N} Lp Val N term <(λ M)@N ≐ (M N)> # betav 1 2
   csiv : {M,N}({x} Lp Val x term <(M x) ≐ (N x)>) ⟶ (λ M) ≐ (λ N) # csiv 3
   
   /T example from the end of the section ❙
   t1 = λ[x] 'z @ ((λ[y] y) @ x)
   t2 = λ[x] 'z @ x
   goal = t1 ≐ t2

   /T The following check succeeds without ever calling the ValRule because the unlock is under a lock.❙
   check: goal 
     = csiv [x] Lm Val x term <
       eq_app (refl 'z) U<betav ([y] y) x>
     >

   /T The following example does not guard the unlock but still succeeds because 'n is indeed a value.❙
   check2 = [n] eq_app (refl 'z) U<betav ([y] y) 'n>

   /T The following negative example fails because x is any term and thus not necessarily a value.❙
   // fail   = [x] eq_app (refl 'z) U<betav ([y] y) x>❙


/T An alternative formulation that uses polymorphpic LF to define most of the typing rules in the logical framework.
   That corresponds to the Coq implementation of LLF_P by Honsell et al.❚
theory LLFP2 : ur:?PLF =
  PROP : type
  DED : PROP ⟶ type
  rule lfrules?TermIrrelevanceRule DED
  
  Lock : {p: PROP} (DED p ⟶ type) ⟶ type# L 1 2
  lock : {p: PROP} {a: DED p ⟶ type} ({p} a p) ⟶ L p a# l 1 3
  unlock : {p, a: DED p ⟶ type} L p a ⟶ {w:DED p} a w# U 3


theory LinearLogic : ?LLFP2 =
  o : type
  ded : o ⟶ type# ded 1 prec -5
  
  linear: {a,b} (ded a ⟶ ded b) ⟶ PROP# linear 3  
  
  lolli : o ⟶ o ⟶ o# 1  2
  lolliI : {A,B} {p:ded A ⟶ ded B} L (linear p) [q] ded A ⊸ B

namespace http://cds.omdoc.org/mmt

import rules scala://api.mmt.kwarc.info

theory Errors =
   // a missing term of a given type ❙ 
   missing   #  1         prec -99500
   // a term not matching a required type ❙
   illtyped  #  1 :: 2    prec -100000
   // an unknown term (e.g., an omitted proof) that uses certain subterms (e.g., the used axioms) ❙
   unknown   #  using 1,  prec -100003

   // this notation clashes with unbracketed lambdas inside some other unknown, removed for now
   // unsolved  # ≪ [ V1T,… ] 2 ≫ prec -100006❙
   
   // an ambiguous term with multiple options; its first argument is the number of the argument that was obtained as the result of disambiguation (starting from 0) ❙
   oneOf     #  1 @ 2,  prec -100002
   
   // infers the type of missing terms❙
   rule rules/checking?HoleTerm
   // reduces disambiguated term ❙
   rule rules/checking?Disambiguation
   // disambiguates terms formed by oneOf ❙
   rule rules/checking?InferAmbiguous

   
theory mmt = 
   // binds unsolved meta-variables ❙
   unknown
   // binds free variables that are implicitly quantified at the toplevel❙
   free
   // the type of all rules❙
   constant rule

   // the type of notations❙
   notation
   // enables notation literals❙ 
   rule rules/notations?NotationRealizedType
   
   rule rules/patterns?PatternFeature
   rule rules/patterns?InstanceFeature
   rule rules/parser?MMTURILexer

   // notations with round brackets must have a lower precedence than this to be recognized ❙
   brackets     # ( 1 ) prec -1000005
   // left bracket with omitted partner as far to the right as consistent with round brackets ❙
   andrewsDot   #  1  prec -1000000
   // right bracket with omitted partner as far to the left as consistent with round brackets ❙
   andrewsDotRight # 1   prec -1000000

namespace http://cds.omdoc.org/urtheories

theory PL =
   oftype   # : 1

   List     # List 1
   list     # [ 1, ]
   
   Option   # Option 1
   some     # some 1
   none     # none
   
   Tuple    # 1× 
   tuple    #  1,  
   proj     # 1 . 2
   
   Function # 1×  2
   lambda   # λ V1T, . -2 prec 20
   apply    # 1@
   
   Nat   # 
   plus  # 1+
   times # 1*
   minus # 1 - 2
   div   # 1 / 2
   less      # 1 < 2
   lesseq    # 1  2
   greater   # 1 > 2
   greatereq # 1  2
   
   Boolean # 
   and     # 1
   or      # 1
   equal   # 1 = 2
   ifte    # if ( 1 ) 2 else 3

   match   # 1 match 2| prec 50
   case    # [ V2T, ] 1  3 prec 5

namespace http://cds.omdoc.org/urtheories

import example http://cds.omdoc.org/examples
import rules scala://moduleexpressions.mmt.kwarc.info
import operators scala://operators.moduleexpressions.mmt.kwarc.info
import metaops scala://meta.operators.moduleexpressions.mmt.kwarc.info

theory ModExp =
	constant theory   # THY
	constant morphism # MOR 1 2
	constant diagram # DIAG 

	complextheory   # block {| L1T, |} prec -1000005
	complexmorphism # [| L1D, |] prec -1000005

	identity        # IDENTITY 1   prec -1
	composition     # COMPOSE 1; prec -1

	// morphismapplication # %L2d!_1 APPLY 2❙


	rule rules?TheoryTypeInhabitable
	rule rules?MorphTypeInhabitable
	rule rules?DiagramTypeInhabitable 

	rule rules?TheoryTypeUniverse

	rule rules?AnonymousTheoryInfer
	rule rules?AnonymousDiagramInfer 
	rule rules?ComplexTheoryInfer

	rule rules?MorphCheck
	rule rules?DiagramCheck 

	rule rules?MorphismApplicationTerm
	rule rules?MorphismApplicationCompute


theory Combinators =
	include ?ModExp

	// Yasmine's diagram operators
	   =========================== ❙
	empty # EMPTY 1
	rule metaops?ComputeEmpty 

	extends  # 1 EXTENDED_BY { %L1_L2, } prec -1000000 
	rule metaops?ComputeExtends 

	rename1 # L1  L2 prec -500000
	rename # 1 RENAMING { 2, } prec -1000000 
	rule operators?ComputeRename 

	combine  # COMBINE 1 { 2, } 3 { 4, } prec -2000000
	translate # MIXIN 1 { 2, } 3 { 4, } prec -2000000 
	// rule operators?ComputeMixin ❙
	rule operators?ComputeCombine 

	hom # HOM 1 
	rule operators?ComputeHom 

	// Navid's diagram operators
	   =========================== ❙
	pushout_inclusion # PUSHOUT 1 ALONG 2 prec -2000000 
	rule operators?ComputePushoutAlongInclusion 

	diagram_accessor # 1 . 2 prec -3000000 
	rule metaops?ComputeDiagramAccess

	// The diag from file operator expects a filename as first argument given as a string ❙
	include ?Strings 
	diagram_from_file # DIAG FROM FILE 1 prec -2000000 
	rule metaops?ComputeDiagramFromFile 

	diagram_union # 1UNION prec -2000000 
	rule metaops?ComputeDiagramUnion 

	// diagram_difference_by_diagram # 1 WITHOUT DIAG 2 prec -2000000 ❙
	// rule metaops?ComputeDiagramDifferenceByDiagram ❙

	diagram_difference_by_label # 1 WITHOUT LABEL 2 prec -2000000 
	rule metaops?ComputeDiagramDifferenceByLabel 

	diagram_prefix # PREFIX 1 BY 2 prec -2000000 
	rule metaops?ComputePrefixedDiagram 

	diagram_closure # CLOSE 1 WITHIN DOCUMENT prec -2000000 
	rule metaops?ComputeDiagramClosure 

	// Currently deactivated as Navid's Generalizer ComputationRule not finished
	   generalizer # GENERALIZE 1 ALONG 2 prec -2000000 ❙


theory LFComb =
	include ?LF
	include ?Combinators

namespace http://cds.omdoc.org/urtheories

import rules scala://lf.mmt.kwarc.info

theory GCalculus =
   nabla  #  V1T, . 2 prec -10000

   
theory NablaRules =

namespace http://www.openmath.org/cd

theory OpenMath =
  Object
  mapsto
  naryObject
  binder
  OMI
  // the lexing and checking rule for integer literals, e.g., 1 ❙
  // rule info.kwarc.mmt.api.objects?OMI❙
  OMF
  // the lexing and checking rule for floating point literals ❙
  // rule info.kwarc.mmt.api.objects?OMF❙
  OMSTR
  // the lexing and checking rule for string literals, e.g., "1" ❙
  // rule info.kwarc.mmt.api.objects?OMSTR❙

namespace http://cds.omdoc.org/urtheories

import lf scala://lf.mmt.kwarc.info

theory Bool =
  include ?TermsTypesKinds 
  BOOL  : type
  TRUE  : BOOL
  FALSE  : BOOL


theory Ded : ?LF =
  include ?Bool 
  
  DED   : BOOL ⟶ type # DED 1 prec -5  role Judgment
  rule lf?TermIrrelevanceRule (DED)
  rule lf?PiIrrelevanceRule 
  
  TRUEI : DED TRUE


//   dependently-typed higher-order logic, i.e., LF with booleans and equality❚
theory DHOL : ?PLF =
  include ?Ded 
  
  EQUAL : {a:type} a ⟶ a ⟶ BOOL  # 2 EQ 3 prec 5role Eq
  NOTEQUAL : {a:type} a ⟶ a ⟶ BOOL  # 2 NEQ 3 prec 5
  CONTRA : type = DED FALSE
  
// if : {a:type} bool ⟶ a ⟶ a ⟶ a❙

  REFL  : {A,X:A} DED X EQ X  
  SYM   : {A,X:A,Y} DED X EQ Y ⟶ DED Y EQ X# SYM 4
  TRANS : {A,X:A,Y,Z} DED X EQ Y ⟶ DED Y EQ Z ⟶ DED X EQ Z# 5 TRANS 6 
  
  CONG : {A, B, X, Y: A} DED X EQ Y ⟶ {F: A ⟶ B} DED (F X) EQ (F Y)# 5 CONG 6


theory DHOL2 : ?PLF =
  bool  : type 
  equal : {A:type} A ⟶ A ⟶ bool  # 2  3 prec 5 

  ded  : bool ⟶ type  #  1 prec -5 
  refl  : {A,X:A} ⊦ X ≐ X  # refl %I1 %I2 
  cong : {A, B: type} {F: A ⟶ B} {X, Y: A} ⊦ X ≐ Y ⟶ ⊦ (F X) ≐ (F Y)  # congI 3 6 

  extensionality : {A:type,B:A ⟶ type}{F:{x:A} B x, G:{x:A} B x} ({x: A} ⊦ F x ≐ G x) ⟶ ⊦ F ≐ G  # ext 5 
  eqDed    : {B1,B2:bool} ⊦ B1 ≐ B2 ⟶ ⊦ B1 ⟶ ⊦ B2  # eqded 3 4
  eqI    : {B1,B2:bool} (⊦ B1 ⟶ ⊦ B2) ⟶ (⊦ B2 ⟶ ⊦ B1) ⟶ ⊦ (B1 ≐ B2)  # eqI 3 4 

  symmetry : {A : type}{a,b : A} ⊦ a ≐ b ⟶ ⊦ b ≐ a  = [A][a,b][p] eqded (congI ([x] x ≐ a) p) refl  # symm 4 
  eqFun : {A : type,B : type}{F,G : A ⟶ B} ⊦ F ≐ G ⟶ {a} ⊦ F a ≐ G a  = [A,B][F,G][p][a] congI ([H: A ⟶ B] H a) p # eqfun 5 6 

  true : bool  = ([x:bool] x) ≐ ([x:bool] x) 
  trueI : ⊦ true  = refl 

  forall : {A:type} (A ⟶ bool) ⟶ bool  = [A,P] P ≐ ([x:A] true)  #  2 

  forallI : {A:type, P : A ⟶ bool}({x} ⊦ P x) ⟶ ⊦ ∀[x] P x 
    = [A,P][p] ext ([x: A] eqI ([pf: ⊦ P x] trueI) ([pt: ⊦ true] p x)) 
  forallE : {A:type, P : A ⟶ bool} (⊦ ∀[x]P x) ⟶ {a} ⊦ P a 
    = [A,P][p][a] eqded (eqfun (symm p) a) trueI 


theory Option : ?PLF =
  OPTION : type ⟶ type 
	NONE : {a:type} OPTION a   
	SOME : {a:type} a ⟶ OPTION a 
	MAP : {a: type, b: type} (a ⟶ b) ⟶ OPTION b 

namespace http://cds.omdoc.org/urtheories

theory NatSymbols =
	include ?TermsTypesKinds 
	NAT : type 
	zero : NAT 


theory NatArith : ?LF =
  include ?NatSymbols 
  succ  : NAT ⟶ NAT      
  one   : NAT             
        = succ zero           
  plus  : NAT ⟶ NAT ⟶ NAT 
  times : NAT ⟶ NAT ⟶ NAT 


theory NatRels : ?Ded =
  include ?NatArith 
  LEQ   : NAT ⟶ NAT ⟶ BOOL  # 1 LEQ 2 prec 5
  LESS  : NAT ⟶ NAT ⟶ BOOL  # 1 LESS 2 prec 5
        = [m,n] (succ m) LEQ n
  REFL  : {n} DED n LEQ n


theory NatRules : ?DHOL =
  include ?NatRels 

  eq_leq : {X,Y,Z} DED X EQ Y ⟶ DED Y LEQ Z ⟶ DED X LEQ Z  
  leq_eq : {X,Y,Z} DED X LEQ Y ⟶ DED Y EQ Z ⟶ DED X LEQ Z  
  
  plus_comm  : {X,Y} DED plus X Y EQ plus Y X  
  plus_assoc : {X,Y,Z} DED plus (plus X Y) Z EQ plus X (plus Y Z) 
  plus_neut_Ex : {X} DED plus X zero EQ X  # %%prefix 0 1
  plus_neut    : {X} DED plus X zero EQ X  = [X] plus_neut_Ex X role Simplify 
  
  plus_succ_R : {X,Y} DED plus X (succ Y) EQ succ (plus X Y)role Simplify 
  plus_succ_L : {X,Y} DED plus (succ X) Y EQ succ (plus X Y) role Simplify 
  
  times_comm  : {X,Y} DED times X Y EQ times Y X  
  times_assoc : {X,Y,Z} DED times (times X Y) Z EQ times X (times Y Z)  
  times_neut  : {X} DED times X one EQ Xrole Simplify  
  
  times_zero  : {X} DED times X zero EQ zerorole Simplify  
  times_succ_R : {X,Y} DED times X (succ Y) EQ plus (times X Y) Xrole Simplify 
  times_succ_L : {X,Y} DED times (succ X) Y EQ plus (times X Y) Xrole Simplify 

  distrib     : {X,Y,Z} DED times X (plus Y Z) EQ plus (times X Y) (times X Z) role Simplify
  
  leq_refl    : {X} DED X LEQ X  
  leq_trans   : {X,Y,Z} DED X LEQ Y ⟶ DED Y LEQ Z ⟶ DED X LEQ Z    
  leq_antisym : {X,Y} DED X LEQ Y ⟶ DED Y LEQ X ⟶ DED X EQ Y      
  
  plus_mono     : {X,Y,Z} DED X LEQ Y ⟶ DED (plus X Z) LEQ (plus Y Z)  
  plus_mono_L   : {X,Y,Z} DED X LEQ Y ⟶ DED (plus Z X) LEQ (plus Z Y)   
                = [X,Y,Z,p] leq_eq (eq_leq plus_comm (plus_mono p)) plus_comm
  plus_invmono  : {X,Y,Z} DED (plus X Z) LEQ (plus Y Z) ⟶ DED X LEQ Y  

  theory NatOnly : ?DHOL =
    least         : {X} DED zero LEQ X 
    plus_larger_L : {X,Y} DED X LEQ (plus X Y)  
                  = [X][Y] eq_leq (SYM plus_neut) (plus_mono_L least)  
    plus_larger_R : {X,Y} DED Y LEQ (plus X Y)  
                  = [X][Y] leq_eq plus_larger_L plus_comm
    times_mono    : {X,Y,Z} DED X LEQ Y ⟶ DED (times X Z) LEQ (times Y Z)  
    times_invmono : {X,Y,Z} DED (times X Z) LEQ (times Y Z) ⟶ DED X LEQ Y  
  


import rules scala://lf.mmt.kwarc.info
import uom scala://uom.api.mmt.kwarc.info

theory NatLiteralsOnly =
  include ?NatSymbols 
  rule rules?Realize NAT uom?StandardNat
  rule rules?Realize zero uom?Arithmetic/Zero

    
theory NatLiterals : ?LF =
  include ?NatLiteralsOnly 
  include ?NatArith
  rule rules?Realize one uom?Arithmetic/One
  rule rules?Realize succ uom?Arithmetic/Succ


theory Nat : ?DHOL =
  include ?NatSymbols
  include ?NatRules
  include ?NatRules/NatOnly
  include ?NatLiterals

namespace http://cds.omdoc.org/urtheories

theory Products : ?PLF =
   product : type ⟶ type ⟶ type # 1 PROD 2
   pair : {a, b} a ⟶ b ⟶ a PROD b# PAIR 3 4
   projectLeft : {a,b} a PROD b ⟶ a# PI1 3
   projectRight : {a,b} a PROD b ⟶ b# PI2 3


namespace http://cds.omdoc.org/urtheories/pseudo

theory Brackets =
   // notations with round brackets must have a lower precedence than this to be recognized ❙
   brackets     # ( 1 ) prec -1000005
   // left bracket with omitted partner as far to the right as consistent with round brackets ❙
   andrewsDot   #  1  prec -1000000


theory EliminationForms =
  roundbrackets # 1 ( 2, ) prec -1000010
  squarebrackets # 1 [ 2, ] prec -1000010
  dot # 1 . 2 prec -1000010


theory AssignmentForms =
  roundbrackets # 1 ( 2, ) = 3 prec -1000010
  squarebrackets # 1 [ 2, ] = 3 prec -1000010

namespace http://cds.omdoc.org/qmt

theory QMTTypes =
  query  
  prop   
  basetp 
  tp     


theory QMTQuery =	
	// Precedence -16xxxx❙
	
	// <<left>> union|intersection|difference <<right>> ❙
	Union # 1 or 2 prec -169000 
	Intersection # 1 and 2 prec -169000
	Difference # 1 but not 2 prec -169000
	
	Tuple # (* 1, *) prec -160000
	Projection #  L1 of 2 prec -160000
	
	// binders ❙
	Let # let V1 := 2 in 3 prec -168000
	Mapping # 2 map V1 *=>* 3 prec -168000
	BigUnion # <* 3 | V1 in 2 *> prec -168000
	Comprehension # {* V1 in 2 | 3 *} prec -168000 
	
	// select [from <<start>> until <<end>>]|<<index>> of <<query>>❙
	Slice # select from L1 until L2 of 3 prec -160004
	SliceFrom # select from L1 of 2 prec -160003
	SliceUntil # select until L1 of 2 prec -160002
	Element # select L1 of 2 prec -160001
	
	// component|subobject <<spec>> of <<query>>❙
	Component # component L1 of 2 prec -160000
	SubObject # subobject L1 of 2 prec -160000
	
	I # use L1 for 2 prec -160000 
	Closure # closure of 1 prec -160000
	Singleton # {* 1 *} prec -160000
	
	// related to <<query>> by <<relation>>❙
	Related # related to 1 by 2 prec -160000
	
	// leaf case ❙
	Literal # literal 1 prec -160000
	Literals # literals 1, prec -160000
	Paths # paths 1 prec -160000
	QueryFunctionApply # function L1 2 prec -160000

	
theory QMTJudgements = 
	// Precedence -15xxxx❙
		
	/T Equality of two terms ❙ 
	Equals # V1 2 *==* 3 prec -150000
	
	/T One type has a specific term ❙
	Types # V1 2 *:* 3 prec -150000

	
theory QMTProp = 
	// Precedence -14xxxx❙	

	/T unary type relation ❙
	IsA # 1 isa L2 prec -140000
	
	/T ancestor relation between paths ❙
	PrefixOf # 1 *<<* 2 prec -140000
	
	/T element relation between elements and sets ❙
	IsIn # 1 contains 2 prec -140000
	
	/T emptiness of a set ❙
	IsEmpty # empty 1 prec -140000
	
	/T equality of elements ❙
	Equal # 1 *=* 2 prec -140000
	
	/T negation ❙
	Not # *!* 1 prec -140000
	
	/T And ❙
	And # 1 *&&* 2 prec -140000
	
	/T Or ❙
	Or # 1 *||* 2 prec -140000
	
	/T Forall ❙
	Forall # forall V1 in 2 *.* 3 prec -140000
	
	/T Exists ❙ 
	Exists # exists V1 in 2 *.* 3 prec -140000
	
	/T Holds ❙
	Holds # holds 1 2 prec -140000 

	
theory QMTRelationExp = 
	// Precedence -13xxxx❙
	
	/T base case: an atomic binary relation ❙
	ToObject # object 1 prec -130000
	
	/T base case: the inverse of an atomic binary relation ❙
	ToSubject # subject 1 prec -130000
	
	/T the transitive closure of a relation ❙
	Transitive # *+ 1 prec -130000
	
	/T the symmetric closure of a relation ❙
	Symmetric # symmetric 1 prec -130000 
	
	/T the union of a list of relations ❙
	Choice # choice 1, prec -130000
	
	/T the composition of a list of relations ❙
	Sequence # sequence 1, prec -130000
	
	/T the reflexive relation ❙
	Reflexive # reflexive 1 prec -130000
	
	/T the reflexive relation restricted to a set of paths ❙
	HasType # hastype 1, *--* 2, prec -130000

	
theory QMTBinaries =
	// Precedence -12xxxx❙
	
	DependsOn # dependson prec -120000 
	HasMeta # hasmeta prec -120000 
	Includes # includes prec -120000 
	HasDomain # hasdomain prec -120000 
	HasCodomain # hascodomain prec -120000 
	IsInstanceOf # isinstanceof prec -120000 
	RefersTo # refers prec -120000 
	Declares # declares prec -120000 
	IsAliasFor # isaliasfor prec -120000 
	IsAlignedWith # isalignedwith prec -120000 

	
theory QMTUnaries =
	// Precedence -12xxxx❙
	
	IsDocument # document prec -120000 
	IsTheory # theory prec -120000 
	IsView # view prec -120000 
	IsStructure # structure prec -120000 
	IsConstant # constant prec -120000 
	IsPattern # pattern prec -120000 
	IsInstance # instance prec -120000 
	IsDerivedDeclaration # deriveddeclaration prec -120000 
	IsConAss # conass prec -120000 
	IsStrAss # strass prec -120000 
	IsNotation # notation prec -120000 


theory QMTLiterals = 
	// TODO: Literals ❙


theory QMT =
	// include the MMT base in notations
	include ?mmt ❙

	// TODO: Precedence ❙
	include ?QMTQuery 
	include ?QMTProp 
	include ?QMTRelationExp 
	include ?QMTJudgements 
	include ?QMTUnaries  
	include ?QMTBinaries 
	
	include ?QMTLiterals 
	
	include ?QMTTypes 

namespace http://cds.omdoc.org/urtheories

import rules scala://quotation.mmt.kwarc.info

/T   introduces a primitive type that exposes the type MMT terms of the underlying implementation
This can be seen as a first step towards MMT meta-programming but is used here only to represent quotations.

theory TermLiterals =
  include ?TermsTypesKinds

  /T the type of MMT terms ❙
  termliteral: type

  /T makes all MMT terms (inlcudings ill-typed or ill-scoped ones) literals of type $termliteral$❙
  rule rules?TermLiteralRule


/T   the language features of quotation
This allows quoting terms that are well-typed in the current context.

The concrete syntax uses MMT's string interpolation feature with the identifier q, i.e., q"t" is the quotation of the term t.
Quoted terms are unevaluated, i.e., q"1+1" != q"2". 

Within t, it is allowed to escape back into evaluated terms: q"1+${s}" is the quasiquotation q"1+e" where e is the result of evaluating s.

theory Quotation =
  include ?LF // LF is not actually needed here. But due a current bug, the comments are not type-checked correctly without LF. ❙

  include ?TermLiterals

  /T For any [a:type], $Q a$ is the type of quotations of terms of type $a$.❙
  Quote # Q 1

  /T the quotation operator
     Because of interpolation, this is not a unary operator - instead, the evaluated subterms are replaced with free variables and bundled up in a substitution.
     For example, q"1+${s}+2" is internally represented as quote(l, x/s) where l is the term literal 1+x+2.❙
  quote
  
  /T the evaluation operator: For [a:type, q: Q a], $eval q$ is the evaluation of $q$ of type $a$.❙
  eval # eval 1

  /T the concrete syntax for quotations (using string interpolation)❙
  rule rules?Lexer

  /T the formation rule: For [a:type], $Q a$ is a type.❙
  rule rules?QuoteFormation
  /T the introduction rule: In the simplest case, for [a:type, t:a], the quotation of $t$ has type $Q a$.❙
  rule rules?QuoteIntroduction
  /T the elimination rule: For [a:type, q: Q a], $eval q$ has type $a$.❙
  rule rules?QuoteElimination
  /T the type checking rule: For [a:type], we check [q: Q a] by checking that $eval q$ has type $a$.❙
  rule rules?QuoteTyping
  /T the beta-style reduction rule: For [a:type,t:a] the evaluation of the quotation $t$ reduces to $t$.❙
  rule rules?EvalQuote
  
  /T an auxiliary rule for normalizing quotations:
     For example, it reduces q"1+${q"2"}" to q"1+2".❙
  rule rules?ReduceQuote


/T   LF with quotation❚
theory LFQ =
  include ?Quotation
  include ?LF


/T   a simple test theory ❚
theory QuotingInterpolationExample : ?LFQ =
  a: type
  c: a
  f: a ⟶ a ⟶ a
  
  t: Q a ⟶ Q a = [q] q
  
  q1: Q a = q"f c c"
  q2: Q a = q"f c ${q1}" 
  q3: Q a = q"f c ${t q1}" 
  q4: Q a = q"f c ${t q"f c c"}" 
  q5: Q a = q"f c ${t q"f c ${t q1}"}" 


namespace examples/Quotation

theory ExcludedMiddle : /urtheories?LFQ =
  bool: type
  ded : bool ⟶ type#  1 prec -1
  disj: bool ⟶ bool ⟶ bool# 1  2
  not : bool ⟶ bool# ¬ 1
  em  : {f} ⊦ (eval f) ∨ ¬ (eval f) 


theory PeanoInduction : /urtheories?LFQ =
  include ?ExcludedMiddle
  
  nat:  type
  zero: nat
  succ: nat ⟶ nat

  induction: {f} ⊦ (eval f) zero ⟶ ({n} ⊦ (eval f) n ⟶ ⊦ (eval f) (succ n)) ⟶ ({n} ⊦(eval f) n)

namespace http://cds.omdoc.org/urtheories

theory Scala =
  type
  hasType # : 1
  Any
  Unit
  unit     # ()
  Product  # Product [ 1, ] 
  Tuple    # Tuple [ 1, ]
  Function # Fun [ 1, ] 2
  Lambda   # ( V1T, ) -2 prec -1000010
  List     # List [ 1 ] prec 100
  list     # List ( 1, )
  BigInt
  Double
  Boolean            
  String


theory ScalaOM =
  include ?Scala
  Term
  Context

namespace http://cds.omdoc.org/urtheories

import rules scala://semiformal.mmt.kwarc.info

theory Informal =
  informal
  rule rules?InformalLiterals
  rule rules?InformalTyping


theory Semiformal =
  include ?Informal

  semiformal
  rule rules?SemiformalInterpolation
  rule rules?SemiformalTerm


theory SemiformalInterpolationExample : ?LF =
  include ?Semiformal
  
  nat: type
  plus : nat ⟶ nat ⟶ nat # 1 + 2
  
  test : nat ⟶ nat ⟶ nat  = [x,y] sf"the sum of all number from 1 to ${x+y}":nat
  test2 = [x,y] sf"the product of ${x+y:nat} and ${y+x:nat}":nat

  
namespace http://cds.omdoc.org/urtheories

import rules scala://sequences.mmt.kwarc.info

theory Sequences =
   include ?Typed
   include ?Nat

   rep # 1 ^ 2 prec -20
   rule rules?NTypeTerm
   rule rules?UniverseNType

   ellipsis  # ⟨' 2 | V1T '⟩ prec -10002 
   index     # 1 .. 2 prec 9998 
   flatseq   #  1,  prec 0
   
   foldLeft # foldL 1 2 3 4 

   rule rules?EllipsisInfer
   rule rules?EllipsisTypeCheck
   rule rules?EllipsisEqualityCheck
   rule rules?EllipsisInjective
   rule rules?RepTypeCheck
   rule rules?RepEqualityCheck
   rule rules?ExpandRep
   rule rules?IndexInfer
   rule rules?IndexCompute
   rule rules?FlatseqInjective
   rule rules?SolveArity
   rule rules?LengthAwareApplyTerm
   rule rules?LengthAwareBeta
   rule rules?FoldLeftType 


theory LFS =
   include ?DHOL
   include ?Sequences
  
   rule rules?FlexaryPi
   rule rules?FlexaryLambda
   rule rules?FlexaryApply

namespace http://cds.omdoc.org/urtheories

import rules scala://mmt.kwarc.info

theory Strings : ?LF =
  string : type
  empty  : string
  concat : string ⟶ string ⟶ string # 1 + 2

  rule rules/lf?Realize string rules/api/uom?StandardString  
  rule rules/lf?Realize empty rules/api/uom?StringOperations/Empty  
  rule rules/lf?Realize concat rules/api/uom?StringOperations/Concat  

  rule rules/literals?StandardStringInterpolation string concat


theory StringInterpolationExample : ?Strings =

  c: string
  f: string ⟶ string ⟶ string= [x,y] x + y
  
  q1: string = s"AA"
  q2: string = s"AA ${q1}" 
  q3: string = s"AA ${s"a" + s"b"}" 
  q4: string = s"AA ${f c s"BB"}" 
  q5: string = s"AA ${f c s"BB ${f q1 q1}"}"

namespace http://cds.omdoc.org/urtheories

import rules scala://substructural.mmt.kwarc.info

// This theory is under development.
Its goal is to investigate to what extent substructural languages can be represented in MMT.
This was motivated by a promising initial case study on representing ordered linear logic (done with Jeff Polakow, at LFMTP 2017).❚

//   theory Substructural =
   Sarrow  # 2 - 1 -> 3  prec  -9990❙
   Slambda # [ 1 V2T,… ] 2 prec -10000❙
   Sapply  # 1%w…        prec -10❙

   class # class 1 2  prec 1000❙

   unordered ❙
   leftordered ❙
   rightordered ❙
   
   plain❙
   useall❙
   useonce❙
   linear❙

   rule rules?SArrowTerm❙
   rule rules?SLambdaTerm❙
   rule rules?SApplyTerm❙
   rule rules?SArrowTyping❙
   rule rules?SArrowEquality❙
   rule rules?SArrowBeta❙

namespace http://cds.omdoc.org/urtheories

//   LF as meta-theory means using LF HOAS❚

import rules scala://lf.mmt.kwarc.info

theory Subtyping : ?PLF =
  subtype : {A: type, B: type} type                   # 1 ⊆‍ 2 prec -9980
  refl    : {A} A ⊆‍ A
  trans   : {A,B,C} A ⊆‍ B ⟶ B ⊆‍ C ⟶ A ⊆‍ C
  
  covariant : {A: type, B1: A ⟶ type, B2: A ⟶ type} ({x:A} B1 x ⊆‍ B2 x) ⟶ ({x:A} B1 x) ⊆‍ ({x:A} B2 x) 


theory Inhabitation : ?PLF =
  // "! A" is a judgments for the inhabitation (= non-emptiness) of "A".
     If "A" is empty, so is "!A". If "A" is non-empty, "!A" is a singleton.
     These types are useful when using proofs as judgments as guards, i.e., in situations where only the inhabitation of a type matters, not the choice of inhabitant.
     Also note, that if "A" is a type of proofs, then "! A" is essentially the same type but with proof irrelevance.   

  Inh    : type ⟶ type                      # ! 1 prec 20role Judgment
  // introduction: If we have an inhabitant of "A", then "A" is inhabited.

     This is similar to modal logic's necessitation rule, but we apply it even if there are unboxed assumptions in the context.

  inh    : {A} A ⟶ !A # inh 2
  // The inverse operator does not exist exactly but almost: If we have "!A", we can assume an "x:A" as long as we only use "x" to prove other "!B"-judgments.
  
  More generally, the declarations in this theory only return !-types.
  Thus, adding this theory does not affect the adequacy of an existing encoding.❙
  elim   : {A, B} !A ⟶ (A ⟶ !B) ⟶ !B

  // The operator "inh" is functorial. ❙
  // Note that this is also the modal axiom K ❙
  K      : {A,B} !(A ⟶ B) ⟶ !A ⟶ !B
         = [A,B] [p,q] elim p [r: A ⟶ B] elim q [s: A] inh (r s)

  // Thus, we have: "A ⟶ B" is stronger than "!(A ⟶ B)" is stronger than "!A ⟶ !B" (which is equivalent to "A ⟶ !B").
     Set-theoretically, all 3 are equivalent, but proving the inverse directions requires non-canonically choosing an element, which we cannot do in type theory. ❙
         
  // We can prove that multiple inhabitation operators are redundant.❙
  idempotent : {A} !!A ⟶ !A 
         = [A][p] elim p [a]a
  
  // operationalizes the rule {A, P:!A, Q:!A} P = Q❙
  rule rules/inhabitation?ProofIrrelevance


// an experimental theory for predicate subtypes❚
//   theory PredicateSubtypes : ?PLF =
  include ?Subtyping❙
  include ?Inhabitation❙
  
  Sub    : {A: type} (A ⟶ type) ⟶ type              ❘ # 1 | 2 prec 20❙
  sub    : {A, P} {x: A} !(P x) ⟶ A|P               ❘ # 3 by 4❙

  subA_A    : {A,P} A|P ⊆‍ A❙
  subA_subA : {A,P,Q} ({x} P x ⟶ Q x) ⟶ A|P ⊆‍ A|Q❙

  // elim   : {A,P}{x: A|P} ! (P x)❙
  // sub x (elim x) = x❙

namespace http://cds.omdoc.org/urtheories/reflection

rule scala://parser.api.mmt.kwarc.info?MMTURILexer

theory Terms =
   include ☞/urtheories?Typed
   
   formation # {| 1 |} 2 prec -10000
   reflect   #  1 : 2  prec -10000
   eval      #  1  2   prec -10000
   elim      # 1 ^ 2     prec -10000


theory LFReflection =
  include ☞/urtheories?LF
  include ?Terms

namespace http://mathhub.info/MitM/Foundation 

import rules scala://rules.mitm.mmt.kwarc.info 
import lf scala://lf.mmt.kwarc.info 
import lfx scala://LFX.mmt.kwarc.info 

fixmeta http://cds.omdoc.org/mmt?mmt 

theory Metadata =
	constructorargument 


/T We define a formal language for basic mathematical objects in LF. ❚

theory Subtyping =
	 include ☞http://gl.mathhub.info/MMT/LFX/Subtyping?LFSubtyped 


/T First, some logic. ❚

                                               
theory Logic : http://gl.mathhub.info/MMT/LFX/TypedHierarchy?LFHierarchy =
	 include ☞http://gl.mathhub.info/MMT/LFX/Records?LFRecords 
	 include ☞http://cds.omdoc.org/urtheories?Ded 
	 include ☞http://gl.mathhub.info/MMT/LFX/Subtyping?LFWithVariance 
	 
	 // rule rules?ApplyRule ❙
	 
	 /T the type of booleans, i.e., all formulas are represented as terms of LF-type $prop$ ❙
	 // bool : type ❘ // = BOOL ❙
	 prop : type  @ bool  = BOOL 
	 
	 /T one LF-type for each formula holding its proofs                 
	 For example, the LF type ⊦ 0 ≐ 1 is empty because that formula has no proofs.
	 Axioms are declared as constants of the corresponding type, e.g., a constant of type $⊦ true$ for the axiom of truth.❙
	 ded : prop ⟶ type  #  1 prec -500  role Judgment  = DED 
	 ImplicitProof : {A} ⊦ A  # ImplicitProof 1 
	 rule lf?TermIrrelevanceRule (ded) ([A : prop] ImplicitProof A) 
	 
	 /T Equality on terms. The type A is left implicit and can be inferred by MMT ❙
	 eq : {A:𝒰 100} A ⟶ A ⟶ bool  # 2  3 prec -5  role Eq  // = EQUAL 
	 
	 
	 // coercion : {A : type, P : A ⟶ prop,a} ⊦ P a ⟶ ⟨ A | ([x] ⊦ P x) ⟩ ❘ # coerce 3 %I4❙
	 // coercion_theorem : {A : type,P : A ⟶ prop,a,p : ⊦ P a} ⊦ eq ⟨ A | ([x] ⊦ P x) ⟩ (coercion A P a p) a ❙
	 
	 rule rules?BooleanLiterals 
	 
	 // false_is_FALSE : ded (FALSE ≐ false) ❙
	 // true_is_TRUE : ded (TRUE ≐ true) ❙
	 
	 not  : bool ⟶ bool  # ¬ 1 prec -100 
	 neq : {A: 𝒰 100} A ⟶ A ⟶ prop  # 2  3 prec -5  = [A,a,b] ¬ (a ≐ b) 

	 and  : bool ⟶ bool ⟶ bool# 1  2 prec -110 
	 
	 or : bool ⟶ bool ⟶ bool # 1  2 prec -120  // = [A,B] ¬ (¬A ∧ ¬ B) 
	 implies : bool ⟶ bool ⟶ bool # 1  2 prec -130  // = [A,B] B ∨ ¬A 
	 iff : bool ⟶ bool ⟶ bool  # 1  2 prec -140 // = [A,B] (A ⇒ B) ∧ (B ⇒ A) 
   
	 forall : {A : 𝒰 100} (A ⟶ bool) ⟶ bool  #  2 prec -100
	 exists : {A : 𝒰 100} (A ⟶ bool) ⟶ bool  #  2 prec -100 // = [A,f] ¬ ∀ [x:A] ¬ f x 
	 unique : {A : 𝒰 100} (A ⟶ bool) ⟶ A ⟶ bool  = [A,P,x] ∀ [y:A] P y ⇒ y ≐ x  # unique 2 3 
	 exists_unique : {A : 𝒰 100} (A ⟶ bool) ⟶ bool  # ∃! 2 prec -101  = [A,P] ∃ [x] (P x ∧ unique P x) 
   
	 /T Equality on types (semantics missing) ❙
	 tpeq : type ⟶ type ⟶ bool  # 1 ≐≐ 2 prec -6  role Eq 	 		
	 

	 
theory NaturalDeduction : ur:?LF =
	 include ?Logic 
	 
	 tru_introduction : ⊦ true 
	 fals_elimination : {A} ⊦ false ⟶ ⊦ A 
	 fals_introduction : {A} ⊦ A ⟶ ⊦ ¬ A ⟶ ⊦ false 
	 
	 forall_elim : {A : 𝒰 100, P : A ⟶ bool}⊦ ∀ P ⟶ {x : A}⊦ P x  # forallE 3 4
	 forall_introduction : {A : 𝒰 100, P : A ⟶ bool, p : {x : A}⊦P x}⊦ ∀[x] P x  # forallI 3 

	 and_introduction : {A,B} ⊦ A ⟶ ⊦ B ⟶ ⊦ (A ∧ B) 
	 and_elim_left : {A,B} ⊦ (A ∧ B) ⟶ ⊦ A 
	 and_elim_right : {A,B} ⊦ (A ∧ B) ⟶ ⊦ B 
	 
	 not_introduction : {A} (⊦ A ⟶ ⊦ false) ⟶ ⊦ ¬ A 
	 not_elim : {A} ⊦ ¬ ¬ A ⟶ ⊦ A 

	 tnd : {A} ⊦ A ∨ ¬A  // = [A: bool] not_introduction ([p : ⊦ (¬A ∧ ¬¬A)] fals_introduction (not_elim (and_elim_right p)) (and_elim_left p)) 

	/T Some more rules for convenience. ❙

        or_introduction_right :  {A,B} ⊦ A ⟶ ⊦ (A ∨ B)  # orinr 3
        or_introduction_left :  {A,B} ⊦ B ⟶ ⊦ (A ∨ B)  # orinl 3
        implication_introduction : {A,B} (⊦ A ⟶ ⊦ B) ⟶ ⊦ A ⇒ B  # impli 3
        equiv_introduction : {A,B} ⊦ (A ⇒ B) ⟶ ⊦ (B ⇒ A) ⟶ ⊦ (A ⇔ B)  # equivi 3 4
        or_elimination : {A,B} ⊦ (A ∨ B) ⟶ (⊦ A ⟶ ⊦ C) ⟶ (⊦ B ⟶ ⊦ C) ⟶ ⊦ C  # orelim 3 4 5
        modus_ponens : {A,B} (⊦ A ⇒ B) ⟶ ⊦ A ⟶ ⊦ B  # MP 3 4 
	 
	 /T basic axioms governing Equality. Again, all the type parameters can be left implicit ❙
	 eq_refl : {t:𝒰 100,A: t} ⊦ A ≐ A  # eq_refl 2
	 eq_cong : {t : 𝒰 100, s : 𝒰 100, f : t ⟶ s, A : t, B: t}
	 		⊦ A ≐ B ⟶ ⊦ (f A) ≐ (f B)  # eq_cong 3 6
	 

	 

/T Now some theories that introduce primitive types and literals for them.
     Because literals must modify the parser, they are supplied as rules that are implemented in a plugin.❚   
   
theory NatLiterals : ur:?LF =
	include ?Logic 
	include ?Subtyping 
	include ☞http://cds.omdoc.org/urtheories?NatLiterals 
	include ☞http://cds.omdoc.org/urtheories?NatRels 
	
	nat_lit : type  #   = NAT 
	// rule rules?NatLiterals ❙
	pos_lit : type  = ⟨ n : nat_lit | ⊦ n ≠ 0 ⟩  # ℕ+ 
	rule rules?PosLiterals 
	pos_are_nat : pos_lit <* nat_lit 
	
	succ_nat_lit : nat_lit ⟶ pos_lit 
	rule rules?NatSucc 
	// not needed anymore: rule rules?NatSuccInverse ❙
	
	plus_pos_lit : pos_lit ⟶ pos_lit ⟶ pos_lit 
	rule rules?PosPlus 
	plus_nat_lit : nat_lit ⟶ nat_lit ⟶ nat_lit  = plus 
	// rule rules?NatPlus ❙
   	times_pos_lit : pos_lit ⟶ pos_lit ⟶ pos_lit 
	rule rules?PosTimes 
	times_nat_lit : nat_lit ⟶ nat_lit ⟶ nat_lit = times 
	// rule rules?NatTimes ❙
    leq_nat_lit : nat_lit ⟶ nat_lit ⟶ bool  = LEQ 
	// rule rules?NatLeq ❙

	
theory IntLiterals : ur:?PLF =
	include ?Logic 
	
	int_lit: type  #  
	rule rules?IntegerLiterals 
	
	minus_int_lit : int_lit ⟶ int_lit 
	rule rules?IntMinus 
	plus_int_lit : int_lit ⟶ int_lit ⟶ int_lit 
	rule rules?IntPlus 
  times_int_lit : int_lit ⟶ int_lit ⟶ int_lit 
	rule rules?IntTimes 
  leq_int_lit : int_lit ⟶ int_lit ⟶ bool 
	rule rules?IntLeq 

	
theory RealLiterals : ur:?LF =
	include ?Logic 
   
	real_lit: type  #  
	rule rules?RealLiterals 
	
	leq_real_lit : real_lit ⟶ real_lit ⟶ bool 
   	rule rules?RealLeq 
   	minus_real_lit : real_lit ⟶ real_lit   # - 1 prec 25 
   	rule rules?RealMinus    
   	plus_real_lit : real_lit ⟶ real_lit ⟶ real_lit  # 1 + 2 prec 25 
	rule rules?RealPlus 
   	times_real_lit : real_lit ⟶ real_lit ⟶ real_lit  # 1 × 2 prec 20 
	rule rules?RealTimes 
	
	
	// square_is_pos : {r : ℝ} ⊦ leq_real_lit 0 (times_real_lit r r) ❙
	sqrt  : ℝ ⟶ ℝ 
	rule rules?RealSqrt 

     
theory Literals : ur:?LF =
   include ?RealLiterals 
   include ?NatLiterals 
   include ?IntLiterals 
   include ?Subtyping 

   ints_are_real : int_lit <* real_lit 
   
   nats_are_int : nat_lit <* int_lit 
   nats_are_real : nat_lit <* real_lit 
   
   pos_are_int : pos_lit <* int_lit 
   pos_are_real : pos_lit <* real_lit 
   
   // rule rules?NumberLiterals ❙

   // test : ⊦ leq_lit 0 1 ❘ = tru_introduction ❙
   // test2 : ⊦ nat_lit_succ 1 ≐ 2 ❘ = eq_refl 2 ❙
	 

   
theory Trigonometry : ur:?LF =
	include ?RealLiterals 
	
	tan   : real_lit ⟶ real_lit    
	sin   : real_lit ⟶ real_lit    
	cos   : real_lit ⟶ real_lit    
	atan   : real_lit ⟶ real_lit    
	asin   : real_lit ⟶ real_lit    
	acos   : real_lit ⟶ real_lit    
	
	rule rules?Tan 
	rule rules?Sin 
	rule rules?Cos 
	rule rules?Atan 
	rule rules?Asin 
	rule rules?Acos 

	 
/T String literals are also needed occasionally, e.g., in the LMFDB.❚
 
theory Strings : ur:?LF =
   include ?Logic
   string: type 
	 rule rules?StringLiterals 
	 concat: string ⟶ string ⟶ string


/T Now some more complex types. First lists.❚

theory Lists : ur:?LF =
   include ☞http://gl.mathhub.info/MMT/LFX/Datatypes?LFLists 


theory InformalProofs : ur:?LF = 
  include ?Strings 
   	 
	proofsketch : {A : prop} string ⟶ ⊦ A  # sketch 2 
	byproof : {A,B} ⊦ A ⟶ ⊦ B  # by 3 
	addproofstep : {A,B,C: prop} ⊦ A ⟶ ⊦ B ⟶ ⊦ B  # 4 and 5 
	trivial : {A : prop} ⊦ A  = [A] sketch "trivial"  # trivial %I1 



/T (Finite) sets ❙
theory Sets : ur:?LF =
   include ?Logic❙
   /T the type operator of sets along with its constructors❙
   set: type ⟶ type ❙
   
   empty: {A} (list A) ❘# ∅ 1❘## ∅ %I1 ❙
   cons: {A} A ⟶ (list A) ⟶ (list A)❘ # 2 , 3 ❙ 


/T Multisets ❙

/T "Finite hybrid sets" (mutlisets with possibly negative mutliplicities) ❙

/T Now vectors, i.e., fixed-length lists.❚

theory Vectors : ur:?PLF =
  include ?Logic
	include ?Literals 
	
   /T the type operator of vectors (fixed-length lists) over a given type ❙
   vector : 𝒰 100 ⟶ nat_lit ⟶ type  # 1 ^^ 2 prec 32 
   
   zerovec : {t : 𝒰 100} vector t 0 
   vector_prepend : {t: 𝒰 100,n : nat_lit, a : t, b : vector t n} t ^^ (succ_nat_lit n)  # 3 ; 4


theory Matrices : ur:?LF =
  include ?Logic
	include ?Vectors 
	
  /T the type operator of matrices over a given type❙
  matrix : 𝒰 100 ⟶ nat_lit ⟶ nat_lit ⟶ type  = [T,n,m] vector (vector T m) n 


theory OptionType : ur:?PLF =
	include ?Logic 
	
	Option : 𝒰 100 ⟶ 𝒰 100 
	
	isDefined : {A} Option A ⟶ prop  # isDefined 2
	OptionGet : {A, a : Option A} ⊦ isDefined a ⟶ A  # get 2 %I3 
	
	None : {A : 𝒰 100} Option A  # None 
	None_is_not_Defined : {A : 𝒰 100} ⊦ isDefined (None A) ≐ false 
	Not_None_is_Defined : {A, a : Option A} ⊦ (a ≠ None A) ⟶ ⊦ isDefined a 
	Some : {A: 𝒰 100} A ⟶ Option A  # Some 2 
	Some_is_Defined : {A : 𝒰 100}{a:A} ⊦ isDefined (Some a) 
	get_some : {A : 𝒰 100}{a:A} ⊦ get (Some a) ≐ a 


theory DescriptionOperator : ur:?PLF =
	include ?OptionType 
	
	that : {A:𝒰 100,P:A ⟶ bool} ⊦ (∃! P) ⟶  A  # ι 2 %I3 
	that_proof : {A : 𝒰 100, P : A ⟶ bool, p : ⊦ ∃! P} ⊦ P (that A P p) 
	
	if_then_else_exists_proof : {A,P,a:A,b:A} ⊦ ∃! [x:A] (P ∧ x ≐ a) ∨ (¬ P ∧ x ≐ b)  # iteep 2 3 4
	if_then_else : {A : 𝒰 100, P : bool, a : A, b : A}A  # if 2 then 3 else 4 
		= [A,P,a,b] that A ([x] (P ∧ x ≐ a) ∨ (¬ P ∧ x ≐ b)) (iteep P a b) 
	if_then_else_case : {A : 𝒰 100, P : bool, a : A, b : A}A  = [A,P,a,b] if P then a else b  # case 2  3 . 4 prec 2 
	
	if_true : {A : 𝒰 100, P : bool, a : A, b : A, p : ⊦ P} ⊦ (if P then a else b) ≐ a  // = [A,P,a,b,p] _  
	if_false : {A : 𝒰 100, P : bool, a : A, b : A, p : ⊦ ¬ P } ⊦ (if P then a else b) ≐ b  // = [A,P,a,b,p] _  


theory ProductTypes : http://gl.mathhub.info/MMT/LFX/Sigma?LFSigma =
	// to have it in the meta-theory ❙                       

theory FiniteTypes : http://gl.mathhub.info/MMT/LFX/Finite?LFFinite = 
theory InductiveTypes : http://gl.mathhub.info/MMT/LFX/WTypes?Inductive =
    include ?Logic 


theory Sequences =
	include ☞ur:?Sequences 
	include ☞ur:?LFS 
	include ?Logic 
	
	forall_seq : {A: type}{n} (A^n ⟶ prop) ⟶ prop  # ∀n 3 prec -101 
	exists_seq : {A: type}{n} (A^n ⟶ prop) ⟶ prop  # ∃n 3 prec -101  = [A,n][P] ¬ forall_seq A n [s : A^n] ¬ (P s)


/T Finally, a theory that puts everything together (not recommended, because modularity) ❚

theory Math : ur:?PLF =
	include ?Subtyping 
	include ?Logic 
	include ?NaturalDeduction 
	include ?Literals 
	include ?Trigonometry 
	include ?Strings 
	include ?InformalProofs 
	include ?Lists 
	include ?Vectors 
	include ?Matrices 
	include ?OptionType 
	include ?DescriptionOperator 
	include ?ProductTypes 
	include ?Sequences 

namespace http://mathhub.info/MitM/Foundation/sets 

import fnd http://mathhub.info/MitM/Foundation 

theory Classes : fnd:?Logic =
    class : type 
    cls_element : class ⟶ class ⟶ prop  # 1  2 prec -1 

    axiom_extensionality : {s,t} ⊦ (∀[e] e ∈ s ⇔ e ∈ t) ⇒ s ≐ t  # axiom_extensionality 1 2 

    include ☞fnd:?Subtyping 
    include ☞fnd:?InformalProofs 
    include ☞fnd:?DescriptionOperator 

    set = ⟨ s : class | ⊦ ∃ [C : class] s ∈ C ⟩  # set prec -1 

    emptyclass : set  #  prec -1 
	axiom_emptyClassIsEmpty : {s} ⊦ ¬ s ∈ ∅  # axiom_emptyClassIsEmpty 1 


// implicit view ZFinNBG : ?ZFBase -> ?Classes =
    include ☞fnd:?InformalProofs ❙
    include ☞fnd:?DescriptionOperator ❙
    set = set ❙
    element = [s,t] cls_element s t ❙
    emptyset = emptyclass ❙
    axiom_emptySetIsEmpty = [s: set] axiom_emptyClassIsEmpty s ❙

    axiom_extensionality = [s,t] sketch "from extensionality" ❙
    axiom_separation = [P,s] sketch "axiomatically" ❙
    axiom_regularity = [s] sketch "axiomatically" ❙
    axiom_pairing = [s,t] sketch "axiomatically" ❙
    axiom_union = [s] sketch "axiomatically" ❙
    axiom_powerset = [s] sketch "axiomatically" ❙
    axiom_replacement = [a,f] sketch "axiomatically" ❙


namespace http://mathhub.info/MitM/Foundation/sets 

import fnd http://mathhub.info/MitM/Foundation 

import rules scala://rules.mitm.mmt.kwarc.info 

theory SetTypeConversions : fnd:?Logic =
	include ?Sets 

	elem : set ⟶ type 
	asSet : type ⟶ set 
	setAsElem : {A,a} ⊦ a ∈ A ⟶ elem A  # asTerm 1 2 %I3 
	elemAsSet : {A : type} A ⟶ set  # asElem 2

	axiom_asElemIsElem : {A,a : A} ⊦ (asElem a) ∈ (asSet A) 
	axiom_inverses1 : {s} ⊦ asSet (elem s) ≐ s  role Simplify 
	axiom_inverses2 : {t} ⊦ elem (asSet t) ≐ t  role Simplify 
	axiom_asTermElem1 : {A,a:A} ⊦ asTerm (asSet A) (asElem a) ≐ a  role Simplify 
	axiom_asTermElem2 : {A,a,p:⊦a ∈ A} ⊦ asElem (asTerm A a) ≐ a  role Simplify 

	// rule rules?SetCoercionRule ❙


theory LiftSeparation : fnd:?Logic =
    include ?SetTypeConversions 
    include ?Separation 
    include ☞fnd:?Subtyping 

    axiom_sepIsPredSub : {s,P : set ⟶ prop} ⊦ elem ⟪ s | P ⟫ ≐ ⟨ x : (elem s) | ⊦ P (asElem x) ⟩  role Simplify 
    axiom_predSubIsSep : {t,P : t ⟶ prop} ⊦ asSet ⟨ x : t | ⊦ P x ⟩ ≐ ⟪ asSet t | ([x] P (asTerm (asSet t) x)) ⟫  role Simplify 


theory LiftProduct : fnd:?Logic =
    include ?CartesianProduct 
    include ?KuratowskiPairs 
    include ?SetTypeConversions 
    include ☞fnd:?ProductTypes 

    // axiom_productType : {s,t} ⊦ elem (product s t) ≐ (elem s) × (elem t) ❘ role Simplify ❙
    rule rules?LiftProductType 
    axiom_productSet : {s,t} ⊦ asSet (s × t) ≐ product (asSet s) (asSet t)  role Simplify 
    axiom_pairType : {s,t,S,T} ⊦ asTerm (product S T) (pair s t) ≐ ⟨ (asTerm S s) , (asTerm T t) ⟩  role Simplify 
    axiom_pairSet : {S,T,s : S,t : T} ⊦ asElem ⟨ s , t ⟩ ≐ pair (asElem s) (asElem t)  role Simplify 


// theory LiftRelations : fnd:?Logic =
    include ?Relations ❙
    include ?LiftProduct ❙


    axiom_relType : {a:set,b:set} ⊦ elem (℘ (product a b)) ≐ (elem a ⟶ elem b ⟶ prop) ❘ role Simplify ❙
    axiom_relSet : {A,B} ⊦ asSet (A ⟶ B ⟶ prop) ≐ ℘ (product (asSet A) (asSet B)) ❘ role Simplify ❙
    axiom_relType2 : {a:set,b:set,r: relation a b} ⊦ eq (elem a ⟶ elem b ⟶ prop) (asTerm (℘ (product a b)) r) ([x : elem a, y : elem b] (pair (asElem x) (asElem y)) ∈ r ) ❘ role Simplify ❙
    axiom_relSet2 : {A,B,R : A ⟶ B ⟶ prop} ⊦ asElem R ≐ ⟪ ℘ (product (asSet A) (asSet B)) | ([x] ∃[a] ∃[b] x ≐ pair a b ∧ R (asTerm (asSet A) a) (asTerm (asSet B) b) ) ⟫ ❘ role Simplify ❙


theory LiftOmega : fnd:?Logic =
    include ?SetTypeConversions 
    include ?Infinity 
    include ☞fnd:?NatLiterals 

    axiom_lift_omega : ⊦ elem ω ≐ ℕ  role Simplify 
    axiom_lift_Nat : ⊦ asSet ℕ ≐ ω  role Simplify 
    axiom_lift_zero : ⊦ asTerm ω ∅ ≐ 0  role Simplify 
    axiom_lower_zero : ⊦ asElem 0 ≐ ∅  role Simplify 
    axiom_lift_succ : {n} ⊦ asTerm ω (set_succ n) ≐ succ_nat_lit (asTerm ω n)  role Simplify 
    axiom_lower_succ : {n} ⊦ asElem (succ_nat_lit n) ≐ set_succ (asElem n)  role Simplify 

namespace http://mathhub.info/MitM/Foundation/sets 

import fnd http://mathhub.info/MitM/Foundation 

theory TypedSets : fnd:?Logic =
	 // include base:?Lists ❙
  include ?SetTypeConversions 
  include ?Powerset 
  include ?Separation 
  include ☞fnd:?Subtyping 
  /T the type operator of sets along with its constructors ❙
  setOf: type ⟶ type  = [A] ⟨ x : set | ⊦ x ∈ (℘ (asSet A)) ⟩ 
  fromPred : {A : type} (A ⟶ prop) ⟶ setOf A  = [A,P] ⟪ ℘ (asSet A) | ([x] P (asTerm (asSet A) x)) ⟫  # asSet 2 
  asPred : {A} setOf A ⟶ A ⟶ prop  = [A,s] [x] (asElem x) ∈ s  # asPred 2 

  // setCons: {A} A ⟶ set A ⟶ set A ❘ = [A] [a,P] [x] P x ∨ x ≐ a❘ # 3 <- 2 ❙
  // setList : {A} List A ⟶  set A ❘ # ≪ 2 ≫ ❙
  // inSet : {A : type} A ⟶ set A ⟶ prop ❘ = [A][a,P] P a ❘ # 2 ∈ 3 ❙
  // bsetst : {A} set A ⟶ (A ⟶ prop) ⟶ set A ❘ = [A][P,Q] [x] P x ∧ Q x ❘ # ⟪ 2 | 3 ⟫ ❙
  // fullset : {A} set A ❘ = [A] [x] true ❘ # fullset 1 ❙
   // TODO, need a lot of congruence rules that make sure that setcons ACI ❙

namespace http://mathhub.info/MitM/Foundation/sets 

import fnd http://mathhub.info/MitM/Foundation 

theory Sets : fnd:?Logic =
	set : type 
	element : set ⟶ set ⟶ prop  # 1  2 
	
	emptyset : set  #  

	axiom_emptySetIsEmpty : {s} ⊦ ¬ s ∈ ∅ 

	subset : set ⟶ set ⟶ prop  = [s,t] ∀ [z] z ∈ s ⇒ z ∈ t  # 1  2 
	disjoint : set ⟶ set ⟶ prop  = [s,t] ¬∃[e] e ∈ s ∧ e ∈ t 
	
	prop_extensionality = [s,t](∀[e] e ∈ s ⇔ e ∈ t) ⇒ s ≐ t 
	prop_separation : (set ⟶ prop) ⟶ set ⟶ prop  = [P][s]∃![t]∀[e]e ∈ t ⇔ (e ∈ s ∧ P e) 
	prop_regularity = [s]s ≠ ∅ ⇒ ∃ [e] e ∈ s ∧ (disjoint s e) 
	prop_pairing = [x,y] ∃[z] x ∈ z ∧ y ∈ z 
	prop_pairing_unique = [x,y] ∃![z] x ∈ z ∧ y ∈ z ∧ ∀[w] w ∈ z ⇒ (w ≐ x ∨ w ≐ y) 
	prop_union = [x] ∃![y]∀[z] z ∈ y ⇔ ∃[w] z ∈w ∧ w ∈ x 
	prop_powerset = [x]∃![y] ∀[z] z ∈ y ⇔ z ⊑ x 
	prop_replacement = [A][f : set ⟶ set] ∃![B]∀[z] (z ∈ B ⇔ ∃[a] a ∈ A ∧ z ≐ f a) 


theory Extensionality : fnd:?Logic =
	include ?Sets 
	
	axiom_extensionality : {s,t} ⊦ prop_extensionality s t 


theory Separation : fnd:?Logic =
	include ?Sets 
	include ☞fnd:?DescriptionOperator 
	
	axiom_separation : {P,s} ⊦ prop_separation P s  # axiom_separation 1 2
	sep_constructor : {s : set,P : set ⟶ prop}set  = [s,P] that set ([x] ∀[e]e ∈ x ⇔ (e ∈ s ∧ P e)) (axiom_separation P s) #  1 | 2  prec -1 


theory Intersection : fnd:?Logic =
    include ?Separation 

    intersect : set ⟶ set ⟶ set  = [s,t] ⟪ s | ([x] x ∈ t) ⟫  # 1  2 


theory Regularity : fnd:?Logic =
	include ?Sets 
	
	axiom_regularity : {s} ⊦ prop_regularity s 


theory Pairing : fnd:?Logic =
	include ?Sets 
	include ☞fnd:?InformalProofs 
	include ☞fnd:?DescriptionOperator 

	axiom_pairing : {x,y} ⊦ prop_pairing x y 
	lemma_pairing_unique : {x,y : set} ⊦ prop_pairing_unique x y  # axiom_pairing_unique 1 2  = [x,y] sketch "provable" 
	uopair : set ⟶ set ⟶ set  = [x,y] that set ([z] x ∈ z ∧ y ∈ z ∧ ∀[w] w ∈ z ⇒ (w ≐ x ∨ w ≐ y)) (lemma_pairing_unique x y) 
	singleton : set ⟶ set  = [s] uopair s s 


theory KuratowskiPairs : fnd:?Logic =
	include ?Pairing 

	pair : set ⟶ set ⟶ set  = [x,y] uopair (uopair x y) x 


theory Union : fnd:?Logic =
	include ?Sets 
	include ☞fnd:?DescriptionOperator 
	
	axiom_union : {x} ⊦ prop_union x  # axiom_union 1
	union : set ⟶ set  = [s] that set ([x] ∀[z] z ∈ x ⇔ ∃[w] z ∈w ∧ w ∈ s) (axiom_union s)  #  1 


theory BinaryUnion : fnd:?Logic =
	include ?KuratowskiPairs 
	include ?Union 
	
	binaryunion : set ⟶ set ⟶ set  = [a,b] ⋃ (uopair a b)  # 1  2


theory Powerset : fnd:?Logic =
	include ?Sets 
	include ☞fnd:?DescriptionOperator 
	
	axiom_powerset : {x} ⊦ prop_powerset x  # axiom_powerset 1
	powerset : set ⟶ set  = [x] that set ([y] ∀[z] z ∈ y ⇔ z ⊑ x) (axiom_powerset x)  #  1 


theory CartesianProduct : fnd:?Logic =
	include ?Powerset 
	include ?Separation 
	include ?BinaryUnion 
	
	product : set ⟶ set ⟶ set  = [A,B] sep_constructor (℘ (℘ (A ∪ B))) ([p] ∃[a]∃[b] a ∈ A ∧ b ∈ B ∧ p ≐ pair a b) 


theory Relations : fnd:?Logic =
	include ?CartesianProduct 
	include ☞fnd:?Subtyping 
	
	prop_relation = [s,A,B : set] s ⊑ (product A B)  # prop_relation 1 2 3
	relation : set ⟶ set ⟶ type = [A,B] ⟨ s : set | ⊦ prop_relation s A B ⟩ 


theory Functions : fnd:?Logic =
	include ?Relations 
	include ☞fnd:?InformalProofs 
	
	prop_function = [f,A,B] prop_relation f A B ∧ ∀[x] x ∈ A ⇒ ∃[y] y ∈ B ∧ (pair x y) ∈ f  
	// TODO ❙
	function : set ⟶ set ⟶ type = [A,B] ⟨ s:set | ⊦ prop_function s A B ⟩ 
	setfunapply : {A,B} function A B ⟶ {a : set}⊦ a ∈ A ⟶ set  = [A,B,f,a,p] ι ([x] (pair a x) ∈ f)  # 3 @ 4 %I5 
	theorem_setfun : {A,B,f : function A B, a} ⊦ (f @ a) ∈ B  = [A,B,f,a] sketch "by definition" 


theory Replacement : fnd:?Logic =
	include ?Sets 
	include ☞fnd:?DescriptionOperator 
	
	axiom_replacement : {a,f} ⊦ prop_replacement a f  # axiom_replacement 1 2
	replacement : set ⟶ (set ⟶ set) ⟶ set  = [A,f] that set ([B] ∀[z] (z ∈ B ⇔ ∃[a] a ∈ A ∧ z ≐ f a)) (axiom_replacement A f)  # Img 2 of 1 


theory Infinity : fnd:?Logic =
	include ?BinaryUnion 

	set_succ = [n] n ∪ (singleton n) 
	prop_infinity = [N] ∅ ∈ N ∧ ∀[n] n ∈ N ⇒ (set_succ n) ∈ N 
	omega : set  # ω  = ι [x] prop_infinity x ∧ ∀[z] prop_infinity z ⇒ x ⊑ z


theory ZFBase : fnd:?Logic =
    include ?Extensionality 
	include ?Separation 
	include ?Regularity 
	include ?Pairing 
	include ?Union 
	include ?Powerset 
	include ?Replacement 
	include ?Infinity 


theory FunctionsExtended : fnd:?Logic =
    include ?Functions 

    prop_injective : {A,B} function A B ⟶ prop  = [A,B,f] ∀[x] ∀[y] x ∈ A ∧ y ∈ A ⇒ (f@x ≐ f@y ⇒ x ≐ y)  # prop_injective 3 
    prop_surjective : {A,B} function A B ⟶ prop  = [A,B,f] ∀[y] y ∈ B ⇒ ∃[x] x ∈ A ∧ f@x ≐ y  # prop_surjective 3 
    prop_bijective : {A,B} function A B ⟶ prop  = [A,B,f] prop_injective f ∧ prop_surjective f  # prop_bijective 3 


theory Finite : fnd:?Logic =
    include ?FunctionsExtended 
    include ?Infinity 

    prop_finite : set ⟶ prop  = [s] ∃[n] n ∈ ω ∧ ∃[f : function s n] prop_injective f 
    prop_infinite : set ⟶ prop  = [s] ¬ prop_finite s 


theory ZF : fnd:?Logic =
    include ?ZFBase 
    include ?Finite 
    include ?Intersection 

	setdiff : set ⟶ set ⟶ set = [A,B] ⟪ A | ([x] ¬ x ∈ B) ⟫  # 1 \ 2 
	subtract : set ⟶ set ⟶ set = [A,a] A \ (singleton a)  # 2 - 3 
	symdiff : set ⟶ set ⟶ set = [A,B] (A \ B) ∪ (B \ A)  # 2 Δ 3 


theory Choice : fnd:?Logic =
	include ?Functions 
	prop_choiceFunction = [A,f : function A (⋃ A)] ∀[a] a ∈ A ⇒ (f @ a) ∈ a 
	choice : {A} ⟨ f : function A (⋃A) | ⊦ prop_choiceFunction A f ⟩ 


theory ZFCBase : fnd:?Logic =
    include ?ZFBase 
    include ?Choice 


theory ZFC : fnd:?Logic =
    include ?ZFCBase 
    include ?ZF 

namespace http://mathhub.info/MitM/Foundation/Units 

import rules scala://rules.mitm.mmt.kwarc.info 

theory Dimensions : ur:?LF = 

  /T An SI Dimension. ❙
  dimension : type
  
  include ☞http://mathhub.info/MitM/Foundation?IntLiterals 
  
  /T A normalized representation used for equality reasoning etc. ❙
  NormedDimension : ℤ ⟶ ℤ ⟶ ℤ ⟶ ℤ ⟶ ℤ ⟶ ℤ ⟶ ℤ ⟶ dimension 

  /T We want the actual dimensions as a dimension. ❙
  /T We use the SI base dimensions for this. ❙
  Length : dimension  // = NormedDimension 1 0 0 0 0 0 0
  Time : dimension // = NormedDimension 0 1 0 0 0 0 0
  Mass : dimension // = NormedDimension 0 0 1 0 0 0 0
  Amount : dimension // = NormedDimension 0 0 0 1 0 0 0
  Temperature : dimension // = NormedDimension 0 0 0 0 1 0 0
  Current : dimension // = NormedDimension 0 0 0 0 0 1 0
  LuminousIntensity : dimension // = NormedDimension 0 0 0 0 0 0 1 
  DimNone : dimension // = NormedDimension 0 0 0 0 0 0 0 

  /T Now we want to make even more dimensions. ❙
  DimTimes: dimension ⟶ dimension ⟶ dimension  # 1 *' 2 
  DimDiv: dimension ⟶ dimension ⟶ dimension  # 1 /' 2 
  
  rule rules?DimEq 


theory DimensionsExtended : ur:?LF =
  include ?Dimensions

  // Dimensionless stuff❙
  Information : dimension = DimNone

  // Velocity, Accelleration ❙
  Velocity : dimension = Length /' Time
  Acceleration : dimension = Velocity /' Time

  // Area and Volume❙
  Area : dimension = Length *' Length
  Volume : dimension = Area *' Length
  
  // Densities ❙
  VolumeDensity : dimension = DimNone /' Volume   // # Density //?? 
  AreaDensity : dimension = DimNone /' Area
  LineDensity : dimension = DimNone /' Length

  // Force and Pressure❙                   
  Force : dimension = Mass *' Acceleration
  Pressure : dimension = Force /' Area

  // Electric Charge and Charge Densities❙
  ElectricCharge : dimension = Current *' Time 
  ElectricChargeVolumeDensity : dimension = ElectricCharge *' VolumeDensity  # ElectricChargeDensity
  ElectricChargeAreaDensity : dimension = ElectricCharge *' AreaDensity  # ElectricChargeSurfaceDensity
  ElectricChargeLineDensity : dimension = ElectricCharge *' LineDensity
  
  // Energy and Power❙
  Energy : dimension = Force *' Length 
  Power : dimension = Energy /' Time
  
  // Basic Electrostatic Units❙
  ElectricPotential : dimension = Energy /' ElectricCharge  # Voltage
  ElectricDisplacement : dimension  = ElectricCharge /' Area  
  ElectricCurrentDensity : dimension = Current *' AreaDensity  # Polarization  // # CurrentDensity 
  ElectricField : dimension  = Voltage /' Length  # ElectricFieldIntensity 
  
  // Other Electrical Units❙
  ElectricalResistance : dimension  = Voltage /' Current 
  ElectricalResistivity : dimension  = ElectricalResistance *' Area /' Length 
  ElectricalConductivity : dimension  = DimNone /' ElectricalResistivity  
  ElectricFlux : dimension  = Voltage *' Length  
  ElectricalCapacitance : dimension  = ElectricCharge /' Voltage 
  ElectricalPermittivity : dimension  = ElectricalCapacitance /' Length 
  ElectricalMobility : dimension  = Velocity /' ElectricField 
  
  IonRecombination : dimension  = Volume /' Time 

  // Magnetism // Hoping we don't need that for now
  
  // Heat-related , cf. Thermistor example❙
  Heat : dimension  = Energy  
	// ThermalConductivity : dimension ❘ = Energy /' Length /' Temperature ❙ // TODO Name clash with quantities.mmt ❙
	ThermalHeatFlux : dimension  = Energy /' Area  
  

namespace http://mathhub.info/MitM/Foundation/Units 
import fnd http://mathhub.info/MitM/Foundation 
import rules scala://rules.mitm.mmt.kwarc.info 

//   http://mathhub.info/MMT/physics-units?QEBase ❚

theory Units : fnd:?Logic =
	include ☞http://mathhub.info/MitM/Foundation?RealLiterals 
	include ?Dimensions 
	
	unit : dimension ⟶ type 
	QE : dimension ⟶ type 
	
  	/T Dimensionless Quantity Expressions are real numbers ❙
  	NoneIsReal : ⊦ QE DimNone ≐≐ real_lit 
  	rule rules?NoneIsReal 
  	
	unitappl : {d : dimension} real_lit ⟶ unit d ⟶ QE d  # 2 of 3  ## 2 3 // test... ❙
  	  
  	scalar : {X} QE X ⟶ real_lit  # scalar 2 
  	scalar_commutes : {X : dimension,r, u : unit X} ⊦ scalar (r of u) ≐ r  role Simplify 
  	unitof : {X} QE X ⟶ unit X  # unitof 2 
  	unitof_commutes : {X : dimension,r, u : unit X} ⊦ unitof (r of u) ≐ u  role Simplify 
	
	
	lift : {din : dimension, dout : dimension, f : ℝ ⟶ ℝ, u : unit din ⟶ unit dout}QE din ⟶ QE dout  # unit_lift 3 4 
		= [din,dout,f,u] [x] (f (scalar x)) of (u (unitof x)) 
	
	UnitTimes : {d1, d2} unit d1 ⟶ unit d2 ⟶ unit (d1 *' d2)  # 3 *'' 4 
	UnitDiv : {d1, d2} unit d1 ⟶ unit d2 ⟶ unit (d1 /' d2)  # 3 /'' 4 
	
	rule rules?UnitEq 


theory QEBase : fnd:?Logic =
  /T A base Theory for dimensions ❙
  include ?Units 
  include ?DimensionsExtended

  /T Multiplying with numbers ❙
  // QENMul : {x : dimension} real_lit ⟶ QE x ⟶ QE x ❘ # 2 . 3 ❙

  /T Dividing by numbers ❙
  // QENDiv : {x : dimension} QE x ⟶ real_lit ⟶ QE x ❘ # 2 /. 3 ❙

  /T Multiplying quantity expressions with each other. ❙
  QEMul : {x : dimension} {y: dimension} QE x ⟶ QE y ⟶ QE (x *' y)  # 3  4 
  
  /T Dividing quantity expressions with each other. ❙
  QEDiv : {x : dimension} {y: dimension} QE x ⟶ QE y ⟶ QE (x /' y)  # 3 / 4 

  /T Adding quantity expressions (maintains dimension). ❙
  QEAdd : {x : dimension} QE x ⟶ QE x ⟶ QE x  # 2 ++ 3 
  
  QESubtract : {x: dimension} QE x ⟶ QE x ⟶ QE x  # 2 - 3 
  
  QEMinus : {x: dimension} QE x ⟶ QE x  # ~ 2 
  
  QEEExp : QE DimNone ⟶ QE DimNone  # exp 1 

  QEExp : QE DimNone ⟶ QE DimNone ⟶ QE DimNone  # 1  2 
  
  QEELog : QE DimNone ⟶ QE DimNone  # ln 1 

  QELog : QE DimNone ⟶ QE DimNone ⟶ QE DimNone  # log 1 2 


theory Field : fnd:?Logic =
  include ?QEBase
  
  // For now, it'll be assumed space is of Length dimension by default, 
  but that will have to be specified later for differntiating and integrating
  over fields defined on space of an arbitrary variable dimension❙

  space : type 
  spaceDim: dimension  = Length 

  field : dimension ⟶ type  = [d]	space ⟶ QE d 

	FieldAdd : {d: dimension} field d  ⟶ field d  ⟶ field d  # 2 .+ 3 
	         = [d,f1,f2] [s] (f1 s) ++ (f2 s) 
	FieldSubtract : {d: dimension} field d ⟶ field d  ⟶ field d  # 2 .- 3 
	         = [d,f1,f2] [s] (f1 s) - (f2 s) 
	FieldMul : {d1: dimension, d2: dimension} field d1 ⟶ field d2  ⟶ field (d1 *' d2)  # 3 .* 4 
	         = [d1,d2,f1,f2] [s] (f1 s) ⋅ (f2 s) 
	FieldDiv : {d1: dimension, d2: dimension} field d1 ⟶ field d2  ⟶ field (d1 /' d2)  # 3 ./ 4 
	         = [d1,d2,f1,f2] [s] (f1 s) / (f2 s) 
	FieldMinus : {d: dimension} field d  ⟶ field d  # .~ 2 
	         = [d,f] [s] ~ (f s) 
	         
	FieldEExp : field DimNone ⟶ field DimNone  # exp. 1 
					 = [f] [s] exp (f s) 
					 
	FieldExp : field DimNone ⟶ field DimNone ⟶ field DimNone  # 1 .↑ 2 
					 = [f1,f2] [s] (f1 s) ↑ (f2 s) 
					 
	FieldLog : field DimNone ⟶ field DimNone ⟶ field DimNone  # log. 1 2 
					 = [f1,f2] [s] log (f1 s) (f2 s) 
					 
	FieldELog : field DimNone ⟶ field DimNone  # ln. 1 
					 = [f] [s] ln (f s) 

	FieldEq  : {d: dimension} field d ⟶ field d  ⟶ prop  # 2 .≐ 3 prec -5 
	         = [d,f1,f2] ∀ [s] (f1 s) ≐ (f2 s) 
	         
	FieldInteg : {d} field d ⟶ field (d *' spaceDim)  # ∑. 2 
  
  FieldDeriv : {d} field d ⟶ field (d /' spaceDim)  # Δ. 2 

namespace http://mathhub.info/MitM/Foundation/Units 

theory SIUnits : ?QEBase =
  // include ?InformationBase❙
  
  NormedUnit : {a,b,c,d,e,f,g}unit (NormedDimension a b c d e f g)  # NormedUnit 1 2 3 4 5 6 7 

  Meter : unit Length  // = NormedUnit 1 0 0 0 0 0 0 
  Second : unit Time // = NormedUnit 0 1 0 0 0 0 0
  Kilogram : unit Mass # kg  // = NormedUnit 0 0 1 0 0 0 0
  Mole : unit Amount  // = NormedUnit 0 0 0 1 0 0 0
  Kelvin : unit Temperature // = NormedUnit 0 0 0 0 1 0 0
  Ampere: unit Current // = NormedUnit 0 0 0 0 0 1 0
  Candela : unit LuminousIntensity  // = NormedUnit 0 0 0 0 0 0 1 
  Scalar : unit DimNone  // = NormedUnit 0 0 0 0 0 0 0 


theory UnitsExtended : ?DimensionsExtended =
	include ?SIUnits 
	
	bit : unit Information  = Scalar 
	
	m2 : unit Area  = Meter *'' Meter  #  
	m3 : unit Volume  = m² *'' Meter  #  
	
	mps : unit Velocity  = Meter /'' Second 
	mpss : unit Acceleration  = Meter /'' (Second *'' Second) 
	
	newton : unit Force  = kg *'' mpss  # N 
	pascal : unit Pressure  = N /'' m²  # Pa 
	
	joule : unit Energy  = N *'' Meter 

namespace http://mathhub.info/MitM/core/algebra 
import base http://mathhub.info/MitM/Foundation 

theory IdempotentMagma : base:?Logic = 
	include ?OperationProps 
	include ☞base:?InformalProofs 
	include ?Magma 
		
	theory idempotent_theory : base:?Logic =
		include ?Magma/magma_theory 
		axiom_idempotent : ⊦ prop_idempotent op 
  
  idempotentMagma = Mod ☞?IdempotentMagma/idempotent_theory  role abbreviation 


namespace http://mathhub.info/MitM/core/algebra/bands 

theory Band : base:?Logic = 
  include ☞../algebra?IdempotentMagma
  include ☞../algebra?SemiGroup 
  
  theory band_theory : base:?Logic = 
     include ☞../algebra?IdempotentMagma/idempotent_theory 
     include ☞../algebra?SemiGroup/semigroup_theory 
  
  band = Mod ☞?Band/band_theory  role abbreviation


theory Regular : base:?Logic =
	include ?Band 
	
	theory regular_theory : base:?Logic =
		include ?Band/band_theory 
		axiom_regular : ⊦ ∀[x]∀[y]∀[z] 
			z ∘ x ∘ z ∘ y ∘ z ≐ z ∘ x ∘ y ∘ z 
	


theory LeftNormal : base:?Logic =
	include ?Regular 
	
	theory leftnormal_theory : base:?Logic =
		include ?Band/band_theory 
		axiom_leftnormal : ⊦ ∀[x]∀[y]∀[z] 
			z ∘ x ∘ z ∘ y ≐ z ∘ x ∘ y  
	
	implicit view Reg2LeftNormal : ?Regular/regular_theory -> ?LeftNormal/leftnormal_theory =
		include ?Band/band_theory 
		axiom_regular = sketch "trivial" 
	


theory RightNormal : base:?Logic =
	include ?Regular 
	
	theory rightnormal_theory : base:?Logic =
		include ?Band/band_theory 
		axiom_rightnormal : ⊦ ∀[x]∀[y]∀[z] 
			y ∘ z ∘ x ∘ z ≐ y ∘ x ∘ z 
	
	implicit view Reg2RightNormal : ?Regular/regular_theory -> ?RightNormal/rightnormal_theory =
		include ?Band/band_theory 
	    axiom_regular = sketch "trivial" 
    


theory Normal : base:?Logic =

	include ?LeftNormal 
	include ?RightNormal 
	
	theory normal_theory : base:?Logic =
		include ?Band/band_theory 
		axiom_normal :  ⊦ ∀[x]∀[y]∀[z] 
			z ∘ x ∘ y ∘ z ≐ z ∘ y ∘ x ∘ z 
	
	implicit view LeftNormal2Normal : ?LeftNormal/leftnormal_theory -> ?Normal/normal_theory =
		include ?Band/band_theory 
		axiom_leftnormal = sketch "trivial" 
	

	 implicit view RightNormal2Normal : ?RightNormal/rightnormal_theory -> ?Normal/normal_theory =
		include ?Band/band_theory 
	 	axiom_rightnormal = sketch "trivial" 
    

namespace http://mathhub.info/MitM/core/algebra 
import top http://mathhub.info/MitM/interfaces
import base http://mathhub.info/MitM/Foundation 
import num http://mathhub.info/MitM/core/arithmetics 
import sets http://mathhub.info/MitM/core/typedsets 

theory OperationProps : base:?Logic = 
  prop_idempotent : {U : type} (U ⟶ U ⟶ U) ⟶ prop  = [U,op] ∀[a] op a a ≐ a  # prop_idempotent 2
  prop_associative : {U : type} (U ⟶ U ⟶ U) ⟶ prop  = [U,op] ∀[x : U]∀[y : U]∀[z : U] op x (op y z) ≐ op (op x y) z  # prop_associative 2
  prop_commutative : {U : type} (U ⟶ U ⟶ U) ⟶ prop  = [U,op] ∀[x : U]∀[y] op x y ≐ op y x  # prop_commutative 2
  prop_leftUnital : {U : type} (U ⟶ U ⟶ U) ⟶ U ⟶ prop  = [U,op,e] ∀[x] op e x ≐ x  # prop_leftUnital 2 3 
  prop_rightUnital : {U : type} (U ⟶ U ⟶ U) ⟶ U ⟶ prop  = [U,op,e] ∀[x] op x e ≐ x  # prop_rightUnital 2 3 
  prop_leftCancellative : {U : type} (U ⟶ U ⟶ U) ⟶ prop  = [U,op] ∀[a] ∀[b] ∀[c] op a c ≐ op b c ⇒ a ≐ b  # prop_leftCancellative 2
  prop_rightCancellative : {U : type} (U ⟶ U ⟶ U) ⟶ prop  = [U,op] ∀[a] ∀[b] ∀[c] op c a ≐ op c b ⇒ a ≐ b  # prop_rightCancellative 2
  prop_inverse : {U : type} (U ⟶ U ⟶ U) ⟶ (U ⟶ U) ⟶ U ⟶ bool  = [U,op,inv,e] ∀[x] op x (inv x) ≐ e  # prop_inverse 2 3 4 
  prop_absorption : {U : type} (U ⟶ U ⟶ U) ⟶ (U ⟶ U ⟶ U) ⟶ bool  = [U][m,j] ∀[a] ∀[b] m a (j a b) ≐ a  # prop_absorption 2 3 
  prop_distributive : {U : type} (U ⟶ U ⟶ U) ⟶ (U ⟶ U ⟶ U) ⟶ bool 
		= [U][plus,times] ∀ [x] ∀ [y] ∀ [z] (times x (plus y z)) ≐ (plus (times x y) (times x z))  # prop_distributive 2 3 


theory Magma : base:?Logic =
	include ?OperationProps 
	include ☞sets:?SetStructures 
	theory magma_theory : base:?Logic =
		include ☞sets:?SetStructures/setstruct_theory 
		op : U ⟶ U ⟶ U  # 1  2 prec 19 
	     
	magma = Mod ☞?Magma/magma_theory  role abbreviation 
	baseset 	: magma ⟶ type  = [m] (m.universe)  # dom 1 
	operation : {G: magma} (G.universe ⟶ G.universe ⟶ G.universe)  # 2  3 prec 20  = [G] [a,b] (G.op) a b 
	finite: magma ⟶ prop 

	
theory SemiGroup : base:?Logic =
	include ?Magma 

	theory semigroup_theory : base:?Logic =
		include ?Magma/magma_theory 
		axiom_associative : ⊦ prop_associative op 
	
	semigroup = Mod ☞?SemiGroup/semigroup_theory 

	
theory Unital : base:?Logic =
	include ?Magma 

	theory unital_theory : base:?Logic =
		include ?Magma/magma_theory 
		unit : U  # e prec -1 	
		axiom_leftUnital : ⊦ prop_leftUnital op e 
		axiom_rightUnital : ⊦ prop_rightUnital op e 
	
	unital = Mod ☞?Unital/unital_theory  
	
	unitOf 	: {G: unital} dom G  # %I1 e prec 5  = [G] (G.unit) 


theory QuasiGroup : base:?Logic =
	include ☞base:?DescriptionOperator 
	include ☞base:?NaturalDeduction 
	include ?Magma 
	
	theory quasigroup_theory : base:?Logic =
		include ?Magma/magma_theory 
		qg1 : ⊦ ∀[a]∀[b]∃![x] a ∘ x ≐ b 
		qg2 : ⊦ ∀[a]∀[b]∃![y] y ∘ a ≐ b 
	  leftDivision : U ⟶ U ⟶ U  = [a,b] that U ([x] a ∘ x ≐ b) (forallE (forallE qg1 a) b) 
	  rightDivision : U ⟶ U ⟶ U  = [a,b] that U ([x] x ∘ a ≐ b) (forallE (forallE qg2 a) b) 

	
	quasigroup = Mod ☞?QuasiGroup/quasigroup_theory 


theory CancellativeMagma : base:?Logic = 
	include ?Magma 
/T MiKo: use this to make a view into quasisgroup Theory: they are cancellative ❙
  theory cancellativemagma_theory : base:?Logic =
		include ?Magma/magma_theory 
		axiom_leftCancellative : ⊦ prop_leftCancellative op  
		axiom_rightCancellative : ⊦ prop_rightCancellative op 
  

  cancellativemagma = Mod ☞?CancellativeMagma/cancellativemagma_theory 
  
  /T MiKo: how to express the definitions? ❙
  leftCancellative : magma ⟶ bool 
  rightCancellative : magma ⟶ bool 


/T Refactor: a Loop is just a unital Quasigroup ❚
theory Loop : base:?Logic =
	include ?Unital 
	include ☞base:?DescriptionOperator 
	include ☞base:?NaturalDeduction 

	theory loop_theory : base:?Logic =
		include ?Unital/unital_theory 
		inverse : U ⟶ U  # 1 ⁻¹  prec 24 
		axiom_inverse : ⊦ prop_inverse op (inverse) e 
	
	loop = Mod ☞?Loop/loop_theory 

	inverseElement : {U : unital} dom U ⟶ dom U ⟶ prop  = [U][n,m] n ∘ m ≐ unitOf U  
	inverseExists : loop ⟶ prop  = [G] ∀ [x : dom G] ∃ [y : dom G] inverseElement G x y 
	
	inverseOf	: {G: loop} dom G ⟶ dom G  # 2 ⁻¹  prec 25  = [G] [a] (G.inverse) a 

	
theory Monoid : base:?Logic =
	include ?SemiGroup 
	include ?Unital 
	
	theory monoid_theory : base:?Logic =
		include ?SemiGroup/semigroup_theory 
		include ?Unital/unital_theory 
	
	monoid = Mod ☞?Monoid/monoid_theory 
	


theory Group : base:?Logic = 
	include ?Monoid 
	include ?Loop 
	
	theory group_theory : base:?Logic =
		include ?Monoid/monoid_theory  
		include ?Loop/loop_theory 
	
	group = Mod ☞?Group/group_theory 
		
	                                                                           
	inverseOf	: {G: group} dom G ⟶ dom G  # 2 ⁻¹  prec 25  = [G] [a] (G.inverse) a 
	
	include ☞base:?NatLiterals 
	include ☞base:?IntLiterals 
	include ☞base:?InformalProofs 
	include ☞sets:?FiniteCardinality 
	
	automorphisms : group ⟶ ℕ 
	cyclic : group ⟶ prop 
	order : group ⟶ ℕ  = [g] | fullset (baseset g) |
	parity : group ⟶ ℤ 
	solvable : group ⟶ prop 
	degree : group ⟶ ℤ 
	psolvable : group ⟶ ℕ+ ⟶ prop 
	sylow : group ⟶ ℕ+ ⟶ group 


theory AbelianGroup : base:?Logic =
	include ?Group 

	theory abeliangroup_theory : base:?Logic =
		include ?Group/group_theory 		
		axiom_commutative : ⊦ prop_commutative op 
	
	abeliangroup = Mod ☞?AbelianGroup/abeliangroup_theory  role abbreviation 
	

	
theory GroupHomomorphism : base:?Logic =
  include ?Group
  
  theory groupHomomorphism_theory : base:?Logic =
    from : group # A
    to : group # B
    morph : dom A ⟶ dom B
    axiom_morphism : ⊦ ∀[x: dom A] ∀[y: dom A] (B.op) (morph x) (morph y) ≐ morph (x ∘ y)
  
  groupHomomorphism = Mod ☞?GroupHomomorphism/groupHomomorphism_theory
  

namespace http://mathhub.info/MitM/core/algebra/groups 
import fnd http://mathhub.info/MitM/Foundation 
import core http://mathhub.info/MitM/core 


/T This obviously doesn't type check yet ❙
theory ActionOnPolynomials : fnd:?Logic = 
	include ?SymmetricGroup
	include ?GroupAction
	
	/T I think this is what I would want
	   though it is entirely unclear to me right now
	   how one would encode an induced action (if at all)❙	
  symmetricGroupActionOnPolynomials : type = {vars : type} rightGroupActions (SymmetricGroup vars) (Polynomials vars) ❙
  groupActionOnPolynomials : type = {vars : type} {act : rightGroupActions G vars} rightGroupActions G (Polynomials vars) ❙

namespace http://mathhub.info/MitM/core/algebra/groups 

import fnd http://mathhub.info/MitM/Foundation 
import core http://mathhub.info/MitM/core 
import sets hhttp://mathhub.info/MitM/core/sets 

theory GroupActions : fnd:?Logic = 
  include ../algebra?Group 
  include ?Subgroups 
//  include ?SymmetricGroup ❙
    
  theory RightGroupActionsTheory : fnd:?Logic > G : group, Ω : type ❘ =
    act : Ω ⟶ G.universe ⟶ Ω  # 1 ^ 2 prec 10 
    act_property_id : ⊦ ∀[ω : Ω] (ω ^ (G.unit)) ≐ ω 
    act_property_compose : ⊦ ∀[ω : Ω] ∀[g : G.universe] ∀[h : G.universe] ((ω ^ g) ^ h) ≐ (ω ^ ((G.op) g h)) 
  
  rightGroupActions : group ⟶ type ⟶ type  = [G,Ω] Mod `?GroupActions/RightGroupActionsTheory , G , Ω 
  
  asAction : {G : group, Ω : type, act : Ω ⟶ G.universe ⟶ Ω}{p1 :  ⊦ ∀[ω : Ω] (act ω (G.unit)) ≐ ω}
  		{p2 : ⊦ ∀[ω : Ω] ∀[g : G.universe] ∀[h : G.universe] (act (act ω g) h) ≐ (act ω ((G.op) g h))} rightGroupActions G Ω 
  		= [G, Ω, act, p1, p2] [' act := act, act_property_id := p1, act_property_compose := p2 '] 
  
  rightOrbit : {G : group, Ω : type} (rightGroupActions G Ω) ⟶ Ω ⟶ subtypeOf Ω  # rorbit 3 4 
  rightStabiliser : {G : group, Ω : type} (rightGroupActions G Ω) ⟶ Ω ⟶ subgroupOf G  # rstab 3 4
  
  theory LeftGroupActionsTheory : fnd:?Logic > G : group, Ω : type ❘ =
    act : G.universe ⟶ Ω ⟶ Ω  # 1 ^ 2 prec 10 
    act_property_id : ⊦ ∀[ω : Ω] ((G.unit) ^ ω) ≐ ω 
    act_property_compose : ⊦ ∀[ω : Ω] ∀[g : G.universe] ∀[h : G.universe] (h ^ (g ^ ω)) ≐ (((G.op) h g) ^ ω) 
  
  
//  ❙
//  theory GroupActionsByHomomorphismTheory : fnd:?Logic > G : group, Ω : type ❘=
//    acthom : hom G (SymmetricGroup Ω) ❙
//  ❚
//  theory GroupActionsByHomomorphismTheory : fnd?Logic > G : group, X : ??? ❘=
//  ❚

namespace http://mathhub.info/MitM/core/algebra/groups 

import fnd http://mathhub.info/MitM/Foundation 
import core http://mathhub.info/MitM/core 
import sets hhttp://mathhub.info/MitM/core/sets 

theory Subgroups : fnd:?Logic =
  include ../algebra?Group 
  theory subgroups_theory : fnd:?Logic? > G : group ❘ =
  	 universe : subtypeOf (G.universe)  # U 
  	 
  	 op : U ⟶ U ⟶ U  # 1  2 
  	 op_closure : ⊦ ∀ [x : U] ∀ [y : U] (G.op) x y ≐ op x y 
  	 
	 unit : U  # e prec -1 
	 unit_closure : ⊦ (G.unit) ≐ e 
	 
	 inverse : U ⟶ U  # 1 ⁻¹  prec 24 
	 inverse_property : ⊦ ∀ [x] x ∘ x ⁻¹ ≐ e 
	 inverse_closure : ⊦ ∀ [x : U] (G.inverse) x ≐ x ⁻¹ 
	 
	 associative : ⊦ ∀[x : U]∀[y : U]∀[z : U] (x ∘ (y ∘ z)) ≐ ((x ∘ y) ∘ z) 
	 leftunital : ⊦ ∀[x : U] e ∘ x ≐ x 
	 rightunital : ⊦ ∀[x : U] x ∘ e ≐ x 
  

  elementsOf : group ⟶ type  = [G] G.universe 
  subsetsOf : group ⟶ type  = [G] subtypeOf (elementsOf G) 
  subgroupOf : group ⟶ type  // = [G:group] Mod `?Subgroups?subgroups_theory , G 
  index : {G : group} subgroupOf G ⟶ ℕ+ 
 	 


// theory ActionsOnSubgroups : fnd:?Logic =
	include ?Group ❙
	include ?Subgroups ❙
	include ?GroupActions ❙
	
	subgroupConjugation : {G : group} rightGroupActions G (subgroupOf G) ❙
	elementConjugation : {G : group} rightGroupActions G (elementsOf G) ❙
	
	normaliser : {G : group} (subgroupOf G) → (subgroupOf G) ❘ 
						 = [G] [U : subgroupOf G] rstab (subgroupConjugation G) U ❙   
	
	conjugacyClass : {G : group} (subgroupOf G) → subtypeOf (subgroupOf G) ❘
	           = [G] [U : subgroupOf G] rorbit (subgroupConjugation G) U ❙
						 
  centraliser : {G : group} G.domain → (subgroupOf G) ❘
	           = [G] [x : G.domain] rstab (elementConjugation G) x ❙


// theory NormalSubgroups : fnd:?Logic =
	include ?Subgroups ❙
	
	theory NormalSubgroupsTheory : fnd:?Logic > G : group ❘=
		include ?Subgroups/SubgroupsTheory ❙
		
		normal_prop : ⊦ ∀[g : G.domain] ∀[n : domain] ∃[n2 : domain] ((G.op) ((G.op) ((G.inverse) g) n) g) ≐ n2 ❙ 

	
	// This is a HACK ❙
	normalSubgroupOf : group → type ❘ = [g] (ModelsOf `?NormalSubgroups/NormalSubgroupsTheory ) g g ❙


// theory SylowSubgroups : fnd:?Logic = 
	include ?Subgroups ❙
	include core:/arithmetics?intarith ❙
	SylowSubgroups : {G : group} {p : Primes} subtypeOf (subgroupOf G) ❙ 


// theory GroupHomomorphisms : fnd:?Logic = 
	include ?Group ❙
	include ?Subgroups ❙
	include ?NormalSubgroups ❙

	theory GroupHomomorphismsTheory : fnd:?Logic > G : group, H : group ❘ = 
		map : G.domain → H.domain ❙
    morphism_property : ⊦ ∀[x : G.domain] ∀[y : G.domain] (H.op) (map x) (map y) ≐ map ((G.op) x y)❙
 // 
  hom : group → group → type ❘ = ModelsOf `?GroupHomomorphisms/GroupHomomorphismsTheory ❘ # 1 --> 2 ❙

  // Of course the type of kernel should be more precise! ❙
  // kernel : {G : group} {H : group} hom G H → (subgroupOf G) ❙
	kernel : {G : group} {H : group} (hom G H) → (normalSubgroupOf G) ❙
  image : {G : group} {H : group} (hom G H) → (subgroupOf H) ❙	

namespace http://mathhub.info/MitM/core/algebra/groups 

import fnd http://mathhub.info/MitM/Foundation 
import sets http://mathhub.info/MitM/core/sets 
import arith http://mathhub.info/MitM/core/arithmetics 


/T Permutation groups are subgroups of SymmetricGroup(Ω) ❚
theory PermutationGroups =
	include ?Subgroups 
	include ?SymmetricGroup 
	

	permutationGroup : {Ω : type} subgroupOf (symmetricGroup Ω)  # permutationGroup 1 
	// permutationGroupByGenerators : {Ω : type} subtypeOf (symmetricGroup Ω) ⟶ permutationGroup Ω ❙
	
	degree : permutationGroup ⟶ ℕ  = [g] cardinality g



theory PermutationGroupsN =
	include ?Subgroups 
	include ?SymmetricGroup 
	include ?SymmetricGroupOfN 

  permutationGroup : {Ω : type} subgroupOf (symmetricGroup Ω) 
  // permutationGroupByGenerators : {Ω : type} subtypeOf (symmetricGroup Ω) ⟶ permutationGroup Ω ❙

namespace http://mathhub.info/MitM/core/algebra/groups 

import fnd http://mathhub.info/MitM/Foundation 
import sets http://mathhub.info/MitM/core/sets 
import arith http://mathhub.info/MitM/core/arithmetics 

theory StabilizerChain : fnd:?Logic =
	include ?PermutationGroups 
	include ?GroupActions 
	
	/T A step in a Schreier-Sims Stabiliser Chain ❙
	// step : {Ω : type} {G : group} {act : rightGroupActions G Ω} ⟶ 
		{' basept : Ω, orbit : rorbit act basept, stabiliser : rstab act β '} ❙

	
	

namespace http://mathhub.info/MitM/core/algebra/groups 

import fnd http://mathhub.info/MitM/Foundation 
import sets http://mathhub.info/MitM/core/sets 
import arith http://mathhub.info/MitM/core/arithmetics 

theory SymmetricGroup : fnd:?Logic =
  include ../algebra?Group 
  include ../typedsets?Functions 
  include ../typedsets?Bijective 
  
    has_inverse : {Ω : type} ⊦ ∀ [x : bijections Ω Ω] (x ° (bijinv x)) ≐ ([y : Ω] y)  # has_inv 1 
	is_leftunital : {Ω : type} ⊦ ∀ [x : bijections Ω Ω] ([y] y) ° x ≐ x  # is_lu 1 
	is_rightunital : {Ω : type} ⊦ ∀ [x : bijections Ω Ω] x ° ([y] y) ≐ x  # is_ru 1 
	
  
  symmetricGroup : type ⟶ group  // = [Ω] ['
    domain := bijections Ω Ω,
    op := function_composition Ω Ω Ω,

    associative := isassoc Ω Ω Ω Ω,
    
    unit := ([ω : Ω] ω),
    leftunital := is_lu Ω, 
    rightunital := is_ru Ω, 
    
    inverse := ([x : domain] inverse_bijections Ω Ω x),
    inverse_property := has_inv Ω
    '] 
    

  
theory SymmetricGroupOfN : fnd:?Logic =
  include ?SymmetricGroup 
  include arith:?NaturalArithmetics 
  
  symmetricGroupOfN : ℕ+ ⟶ group  = [N] symmetricGroup (fromOneTo N) 

namespace http://mathhub.info/MitM/groups 

import fnd http://mathhub.info/MitM/Foundation 

theory SylowSubgroup : fnd:?Logic =
  // theory SylowSubgroupTheory : 

	
	
  
theory right_coset : fnd:?Logic = 
  include ?subgroup 
  theory right_coset_theory : fnd:?Logic > g:G =
    element : G  # g 
    type_of_coset : type 
  
  FromTheory right_coset : right_coset_theory 
  is_right_coset : ⊦ ∀ [el:right_coset.type_of_coset] ∃[h:H] el ≐ h ∘ g 

  
theory left_coset : fnd:?Logic = 
  include ?subgroup 
  theory left_coset_theory : fnd:?Logic > g:G =
    element : G  # g 
    left_coset : type 
  
  FromTheory left_coset : left_coset_theory 
  is_left_coset : ⊦ ∀ [el:left_coset.type_of_coset] ∃[h:H] el ≐ g ∘ h 

  
theory normal_subgroup : fnd:?Logic =
  include ?subgroup 
  include ?left_coset 
  include ?right_coset 
  include ?set_equality 
  is_normal_subgroup : ⊦ ∀[g:G] left_coset g = right_coset g 


	//T how to handle properties of groups? Being abelian is a property


theory abeliangroup : fnd:?Logic =
	abelian_property : {U : type}{op : U → U → U}prop  = [U][op]∀[x]∀[y] op x y ≐ op y x 
	theory abeliangroup_theory : base:?Logic =
		include ?group/group_theory 
		
		abelianax : ⊦ abelian_property U op 
	
	FromTheory abeliangroup : abeliangroup_theory 
	
	include ?group 
	
	is_abelian : {G : abeliangroup} ⊦ commutative G  = [G] (G.abelianax) 

	
theory group_homomorphism : fnd:?Logic =
  include ?group
  
  theory group_homomorphism_theory : fnd:?Logic = 
    from: group # A
    to: group # B
    map: dom A → dom B
    morphism_property : ⊦ ∀[x: dom A] ∀[y: dom A] (map x) ∘ (map y) ≐ map (x ∘ y)
  
  FromTheory grouphomomorphism : group_homomorphism_theory


theory group_action : fnd:?Logic =
  include ?group 
  
  theory right_group_action_theory : fnd:?Logic > G : group , Ω : type =
    acting: group  = G  # G 
    actee: type  = Ω  # Ω 
    map: actee → dom acting → actee  # 1 ^ 2 prec 15 
    right_group_action_property_id : ⊦ ∀[ω : actee] (ω ^ (unit acting) ≐ ω ) 
    right_group_action_property_prod : ⊦ ∀[ω : actee] ∀[g : dom acting] ∀[h : dom acting] (ω^g)^h ≐ ω^(g∘h)       
  
  FromTheory rightgroupaction : right_group_action_theory 
  
  theory left_group_action_theory : fnd:?Logic > G : group, Ω : type =
    acting : group  = G  # G 
    actee : type  = Ω  # Ω 
    map : dom acting → actee → actee 
    left_group_action_property_id : ⊦ ∀[ω : actee] map (unit acting) ω ≐ ω 
  
  FromTheory leftgroupaction :  left_group_action_theory 
 
  include ?permutation_representation 
  action_from_representation : permutation_representation → rightgroupaction 
    = [pa] 

  
theory permutation_representation : fnd:?Logic =
  include ?group 
  include ?group_homomorphism 
  include ?SymmetricGroup 
  theory permutation_representation_theory : fnd:?Logic > G : group, Ω : type =
    acting_group : group  = G 
    actee_set : type  = Ω 
    hom : acting_group → SymmetricGroup actee_set 
  
  FromTheory permutation_representation : permutation_representation_theory 

  
/T   all other fields of both action and representation are deduced from the group and the set, so i guess this is enough? ❚
view group_action_is_permutation_representation : ?group_action/rightgroupaction  ?permutation_representation/permutation_representation =
  acting_group = acting 
  actee_set = actee 

  
view permutation_representation_is_group_action : ?permutation_representation/permutation_representation  ?group_action/rightgroupaction =
  acting = acting_group 
  actee = actee_set 

  
theory group_action_orbit : fnd:?Logic =
  include ?group_action 
  theory orbit_theory : fnd:?Logic > action : rightgroupaction, α : action.actee =
    ga : rightgroupaction  = action 
    element : ga.actee  = α 
    set : {type : ga.actee} 
    orbit_set_binding : {orb : orbit} ⊦ ∀[x:orb] ∃[g:ga.acting] ga.map α g ≐ x   
    order : 
  
  FromTheory orbit : orbit_theory 

  
theory group_action_stabilizer : fnd:?Logic =
  include ?group_action 
  theory stabilizer_theory : fnd:?Logic > action : rightgroupaction, α : action.actee =
    ga : rightgroupaction  = action 
    element : ga.actee  = α 
    stabilizer : {type : ga.acting} 
    stabilizer_set_binding : ⊦ ∀[g:stabilizer] ga.map α g ≐ α 
    order : 
  

  
theory orbit_stabilizer_theorem : fnd:?Logic =
  include ?group_action 
  include ?group_action_orbit 
  include ?group_action_stabilizer 
  Omega : type 
  G : group 
  action : rightgroupaction G Omega 
  theorem : ⊦ ∀[α:Omega] ((orbit action α).order) × ((stabilizer action α).order) ≐ (G.order) 

  
theory conjugation : fnd:?Logic =
  include ?group 
  include ?group_action 
  G : group 
  Ω : G.dom 
  la : leftgroupaction G Ω 
  ra : rightgroupaction G Ω 
  conjugation : Ω → G.dom → Ω  = [α, g] ra (la (inverseOf g) α) g  

  
// view conjugation : rightgroupaction =
  acting = G ❙
  actee = Ω 

  
theory conjugation_centralizer : fnd:?Logic =
  include ?conjugation 
  include ?group_action_stabilizer 
  centralizer : {G : group, α : G.dom} type  = stabilizer (conjugation G) α     

namespace http://mathhub.info/MitM/core/algebra 

import base http://mathhub.info/MitM/Foundation 

theory HeckeFields : base:?Logic =
	include ?Field 
	
	degree_over_Q : field ⟶ ℕ 


theory HilbertNewforms : base:?Logic =
	include ?HeckeFields 
		hilbertNewform : type 
		
		base_field : hilbertNewform ⟶ field 
		base_field_degree : hilbertNewform ⟶ ℕ 
		
		// level_ideal TODO ❙
		level_norm : hilbertNewform ⟶ ℤ 
		
		dimension : hilbertNewform ⟶ ℕ 


theory HeckeEigenvalues : elliptic_curves?Base =
	include ?HilbertNewforms 
	
	heckePolynomial : hilbertNewform ⟶ (polynomial rationalField) 
	heckeEigenvalues : hilbertNewform ⟶ List (polynomial rationalField) 
	

namespace http://mathhub.info/MitM/core/algebra 
import base http://mathhub.info/MitM/Foundation 
import ts http://mathhub.info/MitM/core/typedsets 

theory SemiLattice : base:?Logic = 
	include ☞base:?InformalProofs 
	include ☞ts:?Relations 
	include algebra/bands?Band
	
  theory semilattice_theory : base:?Logic = 
     include algebra/bands?Band/band_theory 
     
     axiom_commutative : ⊦ prop_commutative op 
     // order : U ⟶ U ⟶ bool ❘ = [a,b] a ≐ a ∘ b ❘ # 1 < 2 ❙
     // axiom_reflexive : ⊦ reflexive (order) ❘ = sketch "trivial" ❙
     // axiom_transitive : ⊦ transitive (order)❘ = sketch "trivial"  ❙
     // axiom_antisymmetric : ⊦ antisymmetric (order) ❘ = sketch "trivial" ❙
  
  semilattice = Mod ☞?SemiLattice/semilattice_theory  role abbreviation 



// view POSetIsMeetSemiLattice : ?SemiLattice/semilattice_theory -> ts:?POSetBounds/posetBounds_theory =
  universe = universe ❙
  op = meet ❙                               
  axiom_idempotent = meetIdempotent ❙
  axiom_associative = meetAssociative ❙
  axiom_commutative = meetCommutative ❙


// view POSetIsJoinSemiLattice : ?SemiLattice/semilattice_theory -> ts:?POSetBounds/posetBounds_theory =
  universe = universe ❙
  op = join ❙                               
  axiom_idempotent = joinIdempotent ❙
  axiom_associative = joinAssociative ❙
  axiom_commutative = joinCommutative ❙


/T MiKo: probably need to say that the meet order is the same as the join-order, i.e. 
in theory SemiLattice/semilattice_theory
  biviewMeet : ⊢ SemilatticeIsPOSet (POSetIsMeetSemiLattice op ) ≐ op 
  biviewJoin : ⊢ SemilatticeIsPOSet (POSetIsJoinSemiLattice op ) ≐ op 

  and in 

theory ts:?POSet/poset_theory
  biviewMeet : ⊢ POSetIsMeetSemiLattice (SemilatticeIsPOSet ord ) ≐ ord 
  biviewMeet : ⊢ POSetIsMeetSemiLattice (SemilatticeIsPOSet ord ) ≐ ord 


theory Lattice : base:?Logic = 
   include ?OperationProps 
   include ?SemiLattice 
   include ☞ts:?POSet 
   
   // implicit view SemilatticeIsPOSet : ts:?POSet/poset_theory -> ?SemiLattice/semilattice_theory =
    include ☞ts:?SetStructures ❙
   // ord = [a,b] a ≐ a ∘ b ❙
   // axiom_reflexive = sketch "trivial" ❙
   // axiom_transitive = sketch "trivial" ❙
   // axiom_antisymmetric = sketch "trivial" ❙


   include ☞ts:?SetStructures 
   
   theory lattice_theory : base:?Logic = 
   	include ☞ts:?SetStructures/setstruct_theory 
    implicit structure meetstruct : ?SemiLattice/semilattice_theory =
        universe = ☞ts:?SetStructures/setstruct_theory?universe 
        op @ meet  # 1  2 
    
    structure joinstruct : ?SemiLattice/semilattice_theory =
        universe = ☞ts:?SetStructures/setstruct_theory?universe 
        op @ join  # 1  2 
        // order = ☞http://mathhub.info/MitM/core/typedsets?PrOSet/proset_theory?order ❙
    
    prop_absorption1 : bool  = prop_absorption meet join 
    prop_absorption2 : bool  = prop_absorption join meet 
    axiom_absorption : ⊦ prop_absorption1 ∧ prop_absorption2 
   
   lattice = Mod ☞?Lattice/lattice_theory 


theory DistributiveLattice : base:?Logic =
	include ?Lattice 
	include ?Ringoid 
  theory distributiveLattice_theory : base:?Logic = 
     include ?Lattice/lattice_theory 
     structure ringoid : ?Ringoid/ringoid_theory =
     	R = ☞ts:?SetStructures/setstruct_theory?universe 
        // plus = join ❙
        // times = meet ❙
     
  
  distributiveLattice = Mod ☞?DistributiveLattice/distributiveLattice_theory 


theory BoundedLattice : base:?Logic = 
   include ?Lattice
   theory boundedLattice_theory : base:?Logic = 
      include ?Lattice/lattice_theory 
      top : U  #  
      bot : U #  
      // axiom_top : ⊦ ∀[a] a ≼ ⊤ ❙ // imported implicitly via SemilatticeIsPOSet ❙
      // axiom_bot : ⊦ ∀[a] ⊥ ≼ a ❙
   
   boundedLattice = Mod ☞?BoundedLattice/boundedLattice_theory 



theory ComplementedLattice : base:?Logic = 
   include ?BoundedLattice
   theory complementedLattice_theory : base:?Logic =
     include ?BoundedLattice/boundedLattice_theory 
     complement : U ⟶ U ⟶ bool  = [a,c] a ⊔ c ≐ ⊤ ∧ a ⊓ c ≐ ⊥  # comp 1 2
     prop_complemented : bool  = ∀[a] ∃[c] comp a c 
     axiom_complemented : ⊦ prop_complemented 
  
  complementedLattice = Mod ☞?ComplementedLattice/complementedLattice_theory 
 

theory BooleanAlgebra : base:?Logic =
  include ?ComplementedLattice
  include ?DistributiveLattice 
  theory booleanAlgebra_theory : base:?Logic = 
     include ?ComplementedLattice/complementedLattice_theory 
     include ?DistributiveLattice/distributiveLattice_theory 
  
  booleanalgebra = Mod ☞?BooleanAlgebra/booleanAlgebra_theory 

namespace http://mathhub.info/MitM/core/algebra 

import base http://mathhub.info/MitM/Foundation 
import num http://mathhub.info/MitM/core/arithmetics 
import sets http://mathhub.info/MitM/core/typedsets 

theory Module : base:?Logic =
	include ?Ring 
	prop_dist1 : {A : type,B : type} (A ⟶ B ⟶ B) ⟶ (B ⟶ B ⟶ B) ⟶ bool  
		= [A,B,itimes,iplus] ∀[r]∀[x]∀[y] itimes r (iplus x y) ≐ iplus (itimes r x) (itimes r y)  # prop_dist1 3 4
	prop_dist2 : {A : type,B : type} (A ⟶ B ⟶ B) ⟶ (A ⟶ A ⟶ A) ⟶ (B ⟶ B ⟶ B) ⟶ bool  
		= [A,B,itimes,plus1,plus2] ∀[r]∀[s]∀[x] itimes (plus1 r s) x ≐ plus2 (itimes r x) (itimes s x)  # prop_dist2 3 4 5
	prop_associative_scalars : {A : type,B : type} (A ⟶ B ⟶ B) ⟶ (A ⟶ A ⟶ A) ⟶ bool 
		= [A,B,itimes,stimes] ∀[r]∀[s]∀[x] itimes r (itimes s x) ≐ itimes (stimes r s) x  # prop_associative_scalars 3 4 
	prop_unit_scalars : {A : type, B : type} (A ⟶ B ⟶ B) ⟶ A ⟶ bool 
		= [A,B,itimes,u] ∀[x] itimes u x ≐ x  # prop_unit_scalars 3 4
	
	theory module_theory : base:?Logic > scalars : ring ❘ =
		scaltp : type  = scalars.universe 
		
		include ?AbelianGroup/abeliangroup_theory 
		
		scalarmult : scaltp ⟶ U ⟶ U  # 1  2 
		axiom_dist1 : ⊦ prop_dist1 scalarmult op
		axiom_dist2 : ⊦ prop_dist2 scalarmult (scalars.rplus) op 
		axiom_associative_scalars : ⊦ prop_associative_scalars scalarmult (scalars.rtimes) 
		axiom_unit_scalars : ⊦ prop_unit_scalars scalarmult (scalars.rone) 
	 
	
	module = [R : ring] Mod ☞?Module/module_theory R 
	
	distributive_right : {R : ring} ⊦ prop_dist2 (R.rtimes) (R.rplus) (R.rplus)  # distributive_right 1 
		
	asModule : {F : ring} module F  = [f] ['
		universe := f.universe,
		op := f.rplus,
		axiom_associative := f.addition/axiom_associative,
		unit := f.rzero,
		axiom_leftUnital := f.addition/axiom_leftUnital,
		axiom_rightUnital := f.addition/axiom_rightUnital,
		inverse := f.rminus,
		axiom_inverse := f.addition/axiom_inverse,
		axiom_commutative := f.addition/axiom_commutative,
		scalarmult := f.rtimes,
		axiom_dist1 := f.axiom_distributive,
		axiom_dist2 := distributive_right f,
		axiom_associative_scalars := f.multiplication/axiom_associative,
		axiom_unit_scalars := f.axiom_leftUnital
	']  # asMod 1 
	
	// include base:?Sequences ❙
	
	// theory finGenFree_module_theory : base:?Logic > scalars : ring ❘ =
		// include ?module/module_theory ❙
		
		// flexary_sum : {n} U^n ⟶ U ❘ = [n,s] foldL op unit n s ❘ # ∑ 2 ❙
		
		// dimension : NAT ❙
		// basis : U^dimension ❙
		// is_basis : ⊦ ∀ [v : U] ∃ [s : scaltp^dimension] v ≐ (∑ ⟨' s..i ⋅ basis..i | i:dimension '⟩) ❙


	
theory Vectorspace : base:?Logic =
	include ?Field 
	include ?Module 
	theory vectorspace_theory : base:?Logic > scalars : field ❘ =
		include ?Module/module_theory (scalars)        
		bminus : U ⟶ U ⟶ U  = [a,b] op a (inverse b)  # 1 - 2
	 
	vectorspace : field ⟶ kind  = [F : field] Mod ☞?Vectorspace/vectorspace_theory F 

	include ?Module 
	
	asVectorspace : {F : field} vectorspace F  = [f] ['
		universe := f.universe,
		op := f.rplus,
		axiom_associative := f.addition/axiom_associative,
		unit := f.rzero,
		axiom_leftUnital := f.addition/axiom_leftUnital,
		axiom_rightUnital := f.addition/axiom_rightUnital,
		inverse := f.rminus,
		axiom_inverse := f.addition/axiom_inverse,
		axiom_commutative := f.addition/axiom_commutative,
		scalarmult := f.rtimes,
		axiom_dist1 := f.axiom_distributive,
		axiom_dist2 := distributive_right f,
		axiom_associative_scalars := f.multiplication/axiom_associative,
		axiom_unit_scalars := f.axiom_leftUnital
	']  # asVectorspace 1 


theory Productspace : base:?Logic =
	include ?Vectorspace 
	include ☞base:?ProductTypes 
	
	product_universe : {F : field} vectorspace F ⟶ vectorspace F ⟶ type  = [F,v1,v2] v1.universe × v2.universe  # 2 x_ 1 3
	product_op : {F : field, v1: vectorspace F, v2: vectorspace F} (v1 x_ F v2) ⟶ (v1 x_ F v2) ⟶ (v1 x_ F v2) 
		= [F,v1,v2] [a,b] ⟨ ((v1.op) (πl a) (πl b)), ((v2.op) (πr a) (πr b))⟩  # 2 xop_ 1 3 
	product_unit : {F : field, v1 : vectorspace F, v2 : vectorspace F} v1 x_ F v2 
		= [F,v1,v2] ⟨ (v1.unit), (v2.unit) ⟩  # product_unit 1 2 3 
	product_inverse : {F : field, v1 : vectorspace F, v2 : vectorspace F}(v1 x_ F v2) ⟶ (v1 x_ F v2) 
		= [F,v1,v2] [x] ⟨ (v1.inverse) πl x, (v2.inverse) πr x ⟩  # product_inverse 1 2 3 
	product_scalarmult : {F : field, v1: vectorspace F, v2: vectorspace F} F.universe ⟶ (v1 x_ F v2) ⟶ (v1 x_ F v2) 
		= [F,v1,v2][α,v] ⟨ ((v1.scalarmult) α (πl v)), ((v2.scalarmult) α (πr v)) ⟩  # product_scalarmult 1 2 3 
		
	product_axiom_associative : {F : field, v1 : vectorspace F, v2 : vectorspace F}
		⊦ prop_associative (v1 xop_ F v2)  # product_axiom_associative 1 2 3 
	product_axiom_leftUnital : {F : field, v1 : vectorspace F, v2 : vectorspace F} 
		⊦ prop_leftUnital	(v1 xop_ F v2) (product_unit F v1 v2)  # product_axiom_leftUnital 1 2 3 
	product_axiom_rightUnital : {F : field, v1 : vectorspace F, v2 : vectorspace F} 
		⊦ prop_rightUnital	(v1 xop_ F v2) (product_unit F v1 v2)  # product_axiom_rightUnital 1 2 3 
	product_axiom_inverse : {F : field, v1 : vectorspace F, v2 : vectorspace F} 
		⊦ prop_inverse (v1 xop_ F v2) (product_inverse F v1 v2) (product_unit F v1 v2) # product_axiom_inverse 1 2 3 
	product_axiom_commutative : {F : field, v1 : vectorspace F, v2 : vectorspace F} 
		⊦ prop_commutative (v1 xop_ F v2)  # product_axiom_commutative 1 2 3 
	product_axiom_dist1 : {F : field, V1 : vectorspace F, V2 : vectorspace F} 
		⊦ prop_dist1 (product_scalarmult F V1 V2) (V1 xop_ F V2)  # product_axiom_dist1 1 2 3 
	product_axiom_dist2 : {F : field, V1 : vectorspace F, V2 : vectorspace F} 
		⊦ prop_dist2 (product_scalarmult F V1 V2) (F.rplus) (V1 xop_ F V2)  # product_axiom_dist2 1 2 3 
	product_axiom_associativeScalars : {F : field, V1 : vectorspace F, V2 : vectorspace F} 
		⊦ prop_associative_scalars (product_scalarmult F V1 V2) (F.rtimes)  # product_axiom_associativeScalars 1 2 3 
	product_axiom_unitScalars : {F : field, V1 : vectorspace F, V2 : vectorspace F} 
		⊦ prop_unit_scalars (product_scalarmult F V1 V2) (F.rone)  # product_axiom_unitScalars 1 2 3 
		
	productspace : {F : field} vectorspace F ⟶ vectorspace F ⟶ vectorspace F  = [F] [v1] [v2] ['
		universe := v1 x_ F v2,
		op := v1 xop_ F v2,
		axiom_associative := product_axiom_associative F v1 v2,
		unit := product_unit F v1 v2,
		axiom_leftUnital := product_axiom_leftUnital F v1 v2,
		axiom_rightUnital := product_axiom_rightUnital F v1 v2,
		inverse := product_inverse F v1 v2,
		axiom_inverse := product_axiom_inverse F v1 v2,
		axiom_commutative := product_axiom_commutative F v1 v2,
		scalarmult := product_scalarmult F v1 v2,
		axiom_dist1 := product_axiom_dist1 F v1 v2,
		axiom_dist2 := product_axiom_dist2 F v1 v2,
		axiom_associative_scalars := product_axiom_associativeScalars F v1 v2,
		axiom_unit_scalars := product_axiom_unitScalars F v1 v2
	']  # 2 ov 3 
	
	
	finite_vectorspace : {F: field} pos_lit ⟶ vectorspace F  # 1 ^ 2 
	// axiom_finite1 : {F : field} ⊦ eq (vectorspace F) (F ^ 1) (asVectorspace F) ❙
	// axiom_sr : {n} ⊦ finite_real_vectorspace (Succ n) ≐ productspace realField ℝ1 (finite_real_vectorspace n) ❙  
	



theory LinearMaps : base:?Logic =
	include ?Productspace 
	
	theory linearMap_theory : base:?Logic > K : field, n1 : ℕ+, n2 : ℕ+ ❘ =
		V1 = K ^ n1 
		V2 = K ^ n2 
		fun : (V1.universe) ⟶ (V2.universe) 
		// insert axioms here...
		..
		.. ❙
	
	
	linearMap : field ⟶ ℕ+ ⟶ ℕ+ ⟶ type  = [K : field][n1 : ℕ+,n2 : ℕ+] Mod ☞?LinearMaps/linearMap_theory K n1 n2  # linearMap 1 2 3
	// L : linearMap realfield 2 3 ❙

namespace http://mathhub.info/MitM/core/algebra 

import base http://mathhub.info/MitM/Foundation 
import arith http://mathhub.info/MitM/core/arithmetics 
import sets http://mathhub.info/MitM/core/typedsets 

theory NaturalMonoid : base:?Logic =
	include ?Monoid 
	include ☞base:?NaturalDeduction 
	include ☞arith:?NaturalArithmetics 
	
	naturalMonoid : monoid  = ['
		universe := ℕ,
		op := ☞arith:?NaturalArithmetics?addition ,
		axiom_associative := forallI [x : ℕ] (forallI [y : ℕ] (forallI [z : ℕ] (associative_plus_nat x y z))) ,
		unit := 0 ,
		axiom_leftUnital := forallI leftunital_plus_nat ,
		axiom_rightUnital := forallI rightunital_plus_nat
	'] 


theory IntegerRing : base:?Logic =                         
	include ?Ring 
	include ☞base:?NaturalDeduction 
	include ☞arith:?IntegerArithmetics 
	
	axiom_intOneNeqZero : ⊦ neq ℤ 1 0  
	
	integerRing : ring  = ['
		universe := ℤ,
		rplus := ☞arith:?IntegerArithmetics?addition ,
		addition/axiom_associative := forallI [x : ℤ] (forallI [y : ℤ] (forallI [z : ℤ] (associative_plus_int x y z))) ,
		rzero := 0 ,
		addition/axiom_leftUnital := forallI ☞arith:?IntegerArithmetics?axiom_leftUnitalPlus ,
		addition/axiom_rightUnital := forallI ☞arith:?IntegerArithmetics?axiom_rightUnitalPlus ,
		rtimes := ☞arith:?IntegerArithmetics?multiplication ,
		multiplication/axiom_associative := forallI [x : ℤ] (forallI [y : ℤ] (forallI [z : ℤ] (associative_times_int x y z))) ,
		rminus := ☞arith:?IntegerArithmetics?uminus ,
		addition/axiom_inverse := forallI (axiom_plusUminus) ,
		addition/axiom_commutative := forallI [x : ℤ] (forallI [y : ℤ] (☞arith:?IntegerArithmetics?axiom_additionCommutative x y)) ,
		axiom_distributive := forallI [x : ℤ] (forallI [y : ℤ] (forallI [z : ℤ] (☞arith:?IntegerArithmetics?axiom_distributive x y z))) ,
		rone := 1 ,
		axiom_oneNeqZero := axiom_intOneNeqZero,
		axiom_leftUnital := forallI ☞arith:?IntegerArithmetics?axiom_leftUnitalTimes ,
		axiom_rightUnital := forallI ☞arith:?IntegerArithmetics?axiom_rightUnitalTimes
	'] 
	
	integerGroup = additiveGroup integerRing 


theory RationalField : base:?Logic =
	include ?Field 
	include ☞arith:?RationalArithmetics 
	include ☞base:?NaturalDeduction 
	
	axiom_ratOneNeqZero : ⊦ neq ℚ 1 0  

	rationalField : field  = ['
		universe := ℚ,
		rplus := ☞arith:?RationalArithmetics?addition ,
		addition/axiom_associative := forallI [x : ℚ] (forallI [y : ℚ] (forallI [z : ℚ] (associative_plus_rat x y z))) ,
		rzero := 0 ,
		addition/axiom_leftUnital := forallI ☞arith:?RationalArithmetics?axiom_leftUnitalPlus ,
		addition/axiom_rightUnital := forallI ☞arith:?RationalArithmetics?axiom_rightUnitalPlus ,
		rtimes := ☞arith:?RationalArithmetics?multiplication ,
		multiplication/axiom_associative := forallI [x : ℚ] (forallI [y : ℚ] (forallI [z : ℚ] (associative_times_rat x y z))) ,
		rminus := ☞arith:?RationalArithmetics?uminus ,
		addition/axiom_inverse := forallI ☞arith:?RationalArithmetics?axiom_plusUminus ,
		addition/axiom_commutative := forallI [x : ℚ] (forallI [y : ℚ] (☞arith:?RationalArithmetics?axiom_commutativePlus x y)) ,
		☞arith:?IntegerArithmetics?axiom_distributive := forallI [x : ℚ] (forallI [y : ℚ] (forallI [z : ℚ] (☞arith:?RationalArithmetics?axiom_distributive x y z))) ,
		rone := 1 ,
		axiom_oneNeqZero := axiom_ratOneNeqZero,
		axiom_leftUnital := forallI ☞arith:?RationalArithmetics?axiom_leftUnitalTimes ,
		axiom_rightUnital := forallI ☞arith:?RationalArithmetics?axiom_rightUnitalTimes ,
		inverse := inverseTyped ,
		axiom_inverse := forallI axiom_inv2 ,
		axiom_commutative := forallI [x : ℚ] (forallI [y : ℚ] ☞arith:?RationalArithmetics?axiom_commutativeTimes x y)
	']  // TODO ugly hack!! ❙
	
	rationalField2 : field  # IntegerRing
	


theory RealField : base:?Logic =
	include ?Field 
	include ☞arith:?RealArithmetics 
	include ☞base:?NaturalDeduction 
	
	axiom_realOneNeqZero : ⊦ neq ℝ 1 0  

	realField : field  = ['
		universe := ℝ,
		rplus := ☞arith:?RealArithmetics?addition ,
		addition/axiom_associative := forallI [x : ℝ] (forallI [y : ℝ] (forallI [z : ℝ] (associative_plus_real x y z))) ,
		rzero := 0 ,
		addition/axiom_leftUnital := forallI ☞arith:?RealArithmetics?axiom_leftUnitalPlus ,
		addition/axiom_rightUnital := forallI ☞arith:?RealArithmetics?axiom_rightUnitalPlus ,
		rtimes := ☞arith:?RealArithmetics?multiplication ,
		multiplication/axiom_associative := forallI [x : ℝ] (forallI [y : ℝ] (forallI [z : ℝ] (associative_times_real x y z))) ,
		rminus := ☞arith:?RealArithmetics?uminus ,
		addition/axiom_inverse := forallI ☞arith:?RealArithmetics?axiom_plusUminus ,
		addition/axiom_commutative := forallI [x : ℝ] (forallI [y : ℝ] (☞arith:?RealArithmetics?axiom_commutativePlus x y)) ,
		☞arith:?IntegerArithmetics?axiom_distributive := forallI [x : ℝ] (forallI [y : ℝ] (forallI [z : ℝ] (☞arith:?RealArithmetics?axiom_distributive x y z))) ,
		rone := 1 ,
		axiom_oneNeqZero := axiom_realOneNeqZero,
		axiom_leftUnital := forallI ☞arith:?RealArithmetics?axiom_leftUnitalTimes ,
		axiom_rightUnital := forallI ☞arith:?RealArithmetics?axiom_rightUnitalTimes ,
		☞arith:?IntegerArithmetics?inverse := ☞arith:?RealArithmetics?inverseTyped ,
		axiom_inverse := forallI ☞arith:?RealArithmetics?axiom_inv2 ,
		axiom_commutative := forallI [x : ℝ] (forallI [y : ℝ] ☞arith:?RealArithmetics?axiom_commutativeTimes x y)
	']  // TODO ugly hack!! ❙
	


theory RealVectorspace : base:?Logic =
	include ?Vectorspace 
	include ?RealField 
	include ?Productspace 
	
	realVec : kind  = vectorspace realField 
	realVec1 : realVec  = asVectorspace realField  # 1 
	realVec2 : realVec  // = productspace realField ℝ1 ℝ1  # 2 
	realVec3 : realVec  // = productspace realField ℝ1 ℝ2  # 3  // takes forever ❙
	// finite_real_vectorspace : pos_lit ⟶ RealVec ❙

	
namespace http://mathhub.info/MitM/core/algebra/permutationgroup 

import base http://mathhub.info/MitM/Foundation 
import sets http://mathhub.info/MitM/core/typedsets 
import algebra http://mathhub.info/MitM/core/algebra

theory Permutations : base:?Logic =
	include ☞base:?Lists 
	include ☞base:?NatLiterals 
	cycle = List ℕ+ 
	permutation : type 
	PermList : (List cycle) ⟶ permutation 
	fromImage : (List ℕ+) ⟶ permutation 


theory GroupAction : base:?Logic =
  include ☞sets:?Bijective
  include ☞algebra:?Group

  theory groupAction_theory : base:?Logic = 
    include ☞algebra:?Group/group_theory 
    X : type
    phi : U ⟶ (bijections X X)  # Φ
    inner_notation : {g : U, x : X} X = [g,x] (Φ g) x # 1 < 2 >    
    is_action : ⊦  ∀[g: U] ∀[h: U] ∀[x:X] g<h<x>> ≐ (g ∘ h)<x>
  
  groupAction = Mod ☞GroupAction/groupAction_theory
  outer_notation : {GX : groupAction, g : dom GX, x : GX.X} GX.X = [GX,g,x] ((GX.phi) g) x # 2 < 3 >    
  
  include ☞../algebra?RationalPolynomials 
  
  polynomialOrbit : {r : ring} group ⟶ multi_polynomial r ⟶ List (multi_polynomial r)  # orbit 2 3  


theory PermutationGroup : base:?Logic =
  include ☞algebra:?Group
  include ☞sets:?Bijective 
  include ?Permutations 
  include ?GroupAction 
  
  theory permutationGroup_theory : base:?Logic =
    include ?GroupAction/groupAction_theory 
    is_injective_action : ⊦ is_injective Φ 
  
  permutationGroup = Mod ☞?PermutationGroup/permutationGroup_theory 
  
  fromPerm: (List permutation) ⟶ permutationGroup 
  generators : permutationGroup ⟶ List permutation 
  dihedralGroup : ℤ ⟶ permutationGroup 
  

theory TransitiveGroupAction : base:?Logic =
  include ?GroupAction
  theory transitiveGroupAction_theory : base:?Logic = 
    include ?GroupAction/groupAction_theory 
    is_transitive : ⊦ ∀[x:X] ∀[y:X] ∃[g:U] (Φ g) x ≐ y 
  
  transitiveGroupAction = Mod ☞?TransitiveGroupAction/transitiveGroupAction_theory 
  
  
  tr_value : transitiveGroupAction ⟶ ℕ 
  transitiveGroup : ℤ ⟶ ℤ ⟶ transitiveGroupAction 	 meta /MitM/Foundation?Metadata?constructorargument degree
  																					 meta /MitM/Foundation?Metadata?constructorargument tr_value 
 
namespace http://mathhub.info/MitM/core/algebra 

import base http://mathhub.info/MitM/Foundation 

theory Polynomials : base:?Logic =
	include ☞base:?Sequences 
	include ?Ring 
	finiteSum : {r:ring, n} (r.universe)^n ⟶ (r.universe)  = [r,n,s] foldL (r.rplus) (r.rzero) n s   #  3 
	power_seq : {r:ring, n : NAT} r.universe ⟶ r.universe  = [r,n,x] foldL (r.rtimes) (r.rone) n ⟨' x | i:n '⟩  # 3 tothe 2 
	polynomial_of : {r : ring, n} (r.universe)^n ⟶ (r.universe) ⟶ (r.universe)  = [r,n,s] [x] ∑ ⟨' ((r.rtimes) (s..i) (x tothe i) ) | i:n '⟩
		 # polynomial_of 3  
	
	OneDimensionalPolynomialsOver : ring ⟶ type = [r] ⟨ f : (r.universe) ⟶ (r.universe) | ⊦ ∃ [n] exists_seq (r.universe) n [s] f ≐ (polynomial_of s)  ⟩ 
	
	polynomialRing : ring ⟶ ring  // TODO 
	
	polynomial : ring ⟶ type  = [r] (polynomialRing r).universe 
	
	multi_polynomial : ring ⟶ type 
	monomial : {r : ring} type  # monomial 1


theory NumberSpaces : base:?Logic =
	include ?RationalField 
	include ?Polynomials 
	
	numberField : (polynomialRing rationalField).universe ⟶ ring 
	galoisGroup : ring ⟶ group 


theory RationalPolynomials : base:?Logic =
	include ?Polynomials 
	include ☞base:?Lists 
	include algebra?RationalField 
	include ☞base:?ProductTypes 
	
	poly_con : {r : ring} string ⟶ List ℚ ⟶ polynomial r  // = [n,s] polynomial_of s 
	
	monomial_con : {r: ring} (List (string × ℕ)) × ℚ ⟶ monomial r  # monomial_con 1 2
	multi_poly_con : {r : ring} List (monomial r) ⟶ multi_polynomial r  # mpoly 2 
	
	// x1 =  "x1" ❙
	// x2 = "x2" ❙
	// test1 = ⟨ x1 , 1 ⟩ ❙
	// m1 = monomial_con rationalField2 ⟨  (⟨ x1 , 1 ⟩ ++ nil) , 3 ⟩ ❙
	// m2 = monomial_con rationalField2 ⟨ (⟨ x2, 1⟩ ++ nil),2⟩ ❙
	// p = mpoly (ls m1,m2) ❙
	
	groebner : {r : ring} List (multi_polynomial r) ⟶ List (multi_polynomial r)  # groebner 2 

namespace http://mathhub.info/MitM/core/algebra 

import base http://mathhub.info/MitM/Foundation 
import arith http://mathhub.info/MitM/core/arithmetics 
import sets http://mathhub.info/MitM/core/typedsets 

theory Ringoid : base:?Logic = 
	include ?Magma 

  theory ringoid_theory : base:?Logic =
    structure addition : ?Magma/magma_theory =
      	universe @ R 
		op @ plus  # 1 + 2 prec 5
	 
	structure multiplication : ?Magma/magma_theory =
			universe = R 
			op  @ times  # 1  2 prec 6
	
    axiom_distributive : ⊦ prop_distributive plus times 
  
  ringoid = Mod ☞?Ringoid/ringoid_theory 


/T MiKo: refactor this with Ringoid ❚
theory Rig : base:?Logic =
	include ?AbelianGroup 
	
	theory rig_theory : base:?Logic =
		include ☞sets:?SetStructures/setstruct_theory 
		structure addition : ?AbelianGroup/abeliangroup_theory =
			universe = ☞sets:?SetStructures/setstruct_theory?universe  # Uadd 
			op @ rplus  # 1 + 2 prec 5
			unit @ rzero  # O 
			inverse @ rminus  # - 1 
		 
		structure multiplication : ?SemiGroup/semigroup_theory =
			universe = ☞sets:?SetStructures/setstruct_theory?universe  # Umult 
			op  @ rtimes  # 1  2 prec 6
		
		unitset = ⟨ x: U | ⊦ x ≠ O ⟩ 
		axiom_distributive : ⊦ prop_distributive rplus rtimes 
	 
	rig = Mod ☞?Rig/rig_theory 
	
	unitsetOf : rig ⟶ type  = [r] r.unitset 
	axiom_rigUnitsetSubtype : {r : rig} r.unitset <* r.universe 
	
	additiveGroup : rig ⟶ abeliangroup  = [r] [' 
		universe := r.universe,
		op := r.rplus ,
		axiom_associative := r.addition/axiom_associative , 
		unit := r.rzero ,
		axiom_leftUnital := r.addition/axiom_leftUnital ,
		axiom_rightUnital := r.addition/axiom_rightUnital ,
		inverse := r.rminus ,
		axiom_inverse := r.addition/axiom_inverse ,
		axiom_commutative := r.addition/axiom_commutative
		'] 
	multiplicative_semigroup : rig ⟶ semigroup  = [r] ['
			universe := r.universe,
			op := (r.rtimes) ,
			axiom_associative := r.multiplication/axiom_associative
		']  // needs proof that ret type = unitset ❙

		
theory Ring : base:?Logic =
	include ?Rig 
		// TODO needs refactoring once structures work ❙
	theory ring_theory : base:?Logic =
		include ?Rig/rig_theory 
		rone : U  # I 
		axiom_oneNeqZero : ⊦ I ≠ O 
		axiom_leftUnital : ⊦ ∀[x : U] I ⋅ x ≐ x 
		axiom_rightUnital : ⊦ ∀[x : U] x ⋅ I ≐ x 
	
	ring = Mod ☞?Ring/ring_theory 

	
	multiplicative_monoid : ring ⟶ monoid  = [r] ['
			universe := r.universe,
			op := r.rtimes,
			axiom_associative := r.multiplication/axiom_associative,
			unit := r.rone,
			axiom_leftUnital := r.axiom_leftUnital,
			axiom_rightUnital := r.axiom_rightUnital
		'] 

		
theory Field : base:?Logic =
	include ?Ring 

	theory field_theory : base:?Logic =
		include ?Ring/ring_theory 
		
		inverse : unitset ⟶ unitset  # 1 ⁻¹  prec 24 
		axiom_inverse : ⊦ ∀ [x : unitset] x ⋅ (x ⁻¹) ≐ I 
		
		axiom_commutative : ⊦ ∀[x : U]∀[y] (x ⋅ y) ≐ (y ⋅ x) 
	
	field : kind  = Mod ☞?Field/field_theory  role abbreviation 

	
	// multiplicative_group : field ⟶ abeliangroup ❘ = [r] ['
			universe := r.unitset,
			op := r.times,
			isassociative := r.timesisassociative,
			unit := r.timesunit,
			leftunital := r.timesleftunital,
			rightunital := r.timesrightunital,
			inverse := r.timesinverse ,
			inverseproperty := r.timesinverseproperty ,
			abelianax := r.timesabelianax
		'] ❙

namespace http://mathhub.info/MitM/core/arithmetics 

import base http://mathhub.info/MitM/Foundation 

theory ComplexNumbers : base:?Logic = 
	include ?RealArithmetics 
	
	complexNumbers: type  #  
	
	/T every real number is also a complex one: ❙
	axiom_realsAreComplex : ℝ <* ℂ 
	axiom_rationalsAreComplex : ℚ <* ℂ 
	axiom_integersAreComplex : ℤ <* ℂ 
	axiom_naturalsAreComplex : ℕ <* ℂ 
	axiom_posAreComplex : ℕ+ <* ℂ 
	// this constructor returns a complex number z with arguments Re(z), Im(z). ❙
	complexNumberConstructor: ℝ ⟶ ℝ ⟶ ℂ  # 1 +i 2 
	
	imaginaryUnit:  = 0 +i 1  # i 
	/T Re returns real part of complex number. ❙
	realPart: ℂ ⟶ ℝ  # Re 1 
	/T Im returns real part of complex number. ❙
	imaginaryPart: ℂ ⟶ ℝ  # Im 1 
	/T Axioms for basic complex functions: ❙
	axiom_complexNumberConstructor_Re: ⊦ ∀[a] ∀[b] Re (a +i b) ≐ a 
	axiom_complexNumberConstructor_Im: ⊦ ∀[a] ∀[b] Im (a +i b) ≐ b 
	axiom_realPartOfReal : {x : ℝ} ⊦ x +i 0 ≐ x 


theory ComplexArithmetic : base:?Logic =
	include ?ComplexNumbers 
	
	/T ComplexConjugate maps a + b i -> a - b i ❙
	complexConjugate: ℂ ⟶ ℂ  = [z] (Re z) +i (- Im z)  # cConj 1 
	
	/T Additive Inverse ❙
	uminus : ℂ ⟶ ℂ  = [x] (- Re x) +i (- Im x)  # - 1 
	
	/T Addition of two complex numbers ❙
	addition: ℂ ⟶ ℂ ⟶ ℂ  = [z1,z2] (arithmetics?RealArithmetics?addition (Re z1) (Re z2)) +i (arithmetics?RealArithmetics?addition (Im z1) (Im z2))  # 1 + 2 
		
	/T Difference of two complex numbers using additive inverse and addition ❙ 
	subtraction: ℂ ⟶ ℂ ⟶ ℂ  = [z1,z2] z1 + (- z2)  # 1 - 2 
	
	/T Multiplication of two complex numbers with each other. ❙
	multiplication: ℂ ⟶ ℂ ⟶ ℂ 
													= [z1,z2] (☞?RealArithmetics?addition ((Re z1) ⋅ (Re z2)) ( ☞?RealArithmetics?uminus (Im z1) ⋅ (Im z2)))
																			 +i (☞?RealArithmetics?addition ((Re z2) ⋅ (Im z1)) ( (Re z1) ⋅ (Im z2))) 
													# 1  2 
	
	/T Magnitude of  a + b i maps to sqrt(a*a+b*b)... ❙
	complexAbsoluteSquared : ℂ ⟶ ℝ  = [z] Re (z ⋅ cConj z)  # | 1 |^ 
	absolute : ℂ ⟶ ℝ  = [z] sqrt (|z|^)  # |1| 												
		
	nonzeroComplexNumbers : type  # ℂ*  = ⟨ z : ℂ | ⊦ Re z ≠ 0 ∨ Im z ≠ 0 ⟩
	inverse : ℂ* ⟶ ℂ # inv 1 prec 31 
	division: ℂ ⟶ ℂ* ⟶ ℂ  = [u,z] u ⋅ (inv z)  # 1 / 2 
	
namespace http://mathhub.info/MitM/core/arithmetics 

import base http://mathhub.info/MitM/Foundation 

theory IntegerNumbers : base:?Logic =
	include ?NaturalNumbers 
	include ☞base:?IntLiterals 
	
	axiom_natsAreInt : nat_lit <* int_lit 
	axiom_natsAreInt2 : NAT <* int_lit 
	axiom_posAreInt : pos_lit <* int_lit 
	negative : ℤ ⟶ ℤ  = minus_int_lit
	axiom_negZeroIsZero : ⊦ negative 0 ≐ 0 
	axiom_negPosIsNotId: {n : ℕ+} ⊦ neq int_lit (negative n) n 
	axiom_negPosIsInj: {n,m: ℕ} ⊦ negative n ≐ negative m ⟶ ⊦ n ≐ m 


theory IntegerArithmetics : base:?Logic =
	include ?NaturalArithmetics 
	include ?IntegerNumbers 

	/T Negation ❙
	uminus : ℤ ⟶ ℤ  # - 1 prec 34  = minus_int_lit 
	axiom_uminusIsNeg : {n: ℕ} ⊦ -n ≐ negative n 
	axiom_uminusIsNilp : {z:ℤ} ⊦ - (- z) ≐ z 

	/T Addition ❙
	addition : ℤ ⟶ ℤ ⟶ ℤ  # 1 + 2 prec 14  = plus_int_lit 
	axiom_intPlusIsNatplus : {x : ℕ, y : ℕ} ⊦ arithmetics?IntegerArithmetics?addition x y ≐ arithmetics?NaturalArithmetics?addition x y  
	axiom_additionCommutative : {x : ℤ, y : ℤ} ⊦ x + y ≐ y + x  # axiom_additionCommutative 
	axiom_plusUminus : {x : ℤ} ⊦ x + (-x) ≐ 0  # axiom_plusUminus 
	
	/T Subtraction ❙
	subtraction : ℤ ⟶ ℤ ⟶ ℤ  = [a,b] a + (-b)  # 1 - 2 prec 14 
	
	/T Multiplication ❙	
	multiplication : ℤ ⟶ ℤ ⟶ ℤ  #  1  2 prec 24  = times_int_lit 
	axiom_intTimesIsNattimes : {x : ℕ, y : ℕ} ⊦ arithmetics?IntegerArithmetics?multiplication x y ≐ arithmetics?NaturalArithmetics?multiplication x y 
	
	/T Division ❙
	div : {x : ℤ, y : ℤ, p : ⊦ ∃! [z] y ⋅ z ≐ x} ℤ  = [x,y,p] ι [z] y ⋅ z ≐ x  # 1 / 2 %I3 prec 24 

	/T Exponentiation ❙
	exponentiation : ℤ ⟶ ℤ ⟶ ℤ  #  1 ^ 2 prec 34 
	axiom_intExpIsNatexp : {x : ℕ, y : ℕ} ⊦ arithmetics?IntegerArithmetics?exponentiation x y ≐ arithmetics?NaturalArithmetics?exponentiation x y 
	
	/T Roots ❙
	root : {n : ℤ, m : ℕ, p : ⊦ ∃![x] x^m ≐ n}ℤ  = [n,m,p] ι [x] x^m ≐ n   # 2  1 %I3 prec 34 
	// squareRoot : {n : ℤ, p : ⊦ ∃![m] m^2 ≐ n}ℤ ❘ = [n,p] 2 √ n ❘ # √ 1 %I2 prec 34 ❙
	// squareRoot is technically only defined on naturals anyway ❙
	
	/T Order ❙
	leq : ℤ ⟶ ℤ ⟶ bool  = [x,y] ∃ [n: ℕ] eq ℤ (arithmetics?IntegerArithmetics?addition x n) y  # 1  2 prec 104 
	geq : ℤ ⟶ ℤ ⟶ bool  = [n,m] m ≤ n  # 1  2 prec 104 
	lessthan : ℤ ⟶ ℤ ⟶ bool  = [n,m] n ≤ m ∧ n ≠ m  # 1 < 2 prec 104 
	morethan : ℤ ⟶ ℤ ⟶ bool  = [n,m] n ≥ m ∧ n ≠ m  # 1 > 2 prec 104 
	max : ℤ ⟶ ℤ ⟶ ℤ  # max 1 2 
	min : ℤ ⟶ ℤ ⟶ ℤ  # min 1 2 
	axiom_intLeqIsNatLeq : {x : ℕ, y : ℕ} ⊦ arithmetics?NaturalArithmetics?leq x y ≐ arithmetics?IntegerArithmetics?leq x y 

	/T Others ❙
	mod : ℤ ⟶ ℤ ⟶ ℤ  # 1 mod 2 prec 24 

	up : {z : ℤ, p : ⊦ z ≥ 0}ℕ  # ℤtoℕ 1 %I2 
	axiom_up : {n : ℕ,p : ⊦ n ≥ 0} ⊦ ℤtoℕ n ≐ n 
	
	// natissub : ℕ ≐≐ ⟨ ℤ | ([z] ⊦ ¬ z < 0) ⟩ ❙
	
	posisneqzero : ℕ+ <* ⟨ x: ℤ | ⊦ x ≠ 0 ⟩ 
	
	absolute : ℤ ⟶ ℕ  // ❘ = [z] case z <0 ⟹ up (-z) . up z ❘ # | 1 | prec 10 ❙
	// TODO: axioms for the other ones as well.❙
	
	/T Group Axioms ❙
	axiom_associativePlus : {x: ℤ,y,z} ⊦ arithmetics?IntegerArithmetics?addition x (arithmetics?IntegerArithmetics?addition y z) ≐ 
		arithmetics?IntegerArithmetics?addition (arithmetics?IntegerArithmetics?addition x y) z  # associative_plus_int 1 2 3
	axiom_associativeTimes : {x: ℤ,y,z} ⊦ x ⋅ (y ⋅ z) ≐ (x ⋅ y) ⋅ z  # associative_times_int 1 2 3 
	axiom_leftUnitalPlus : {x : ℤ} ⊦ arithmetics?IntegerArithmetics?addition 0 x ≐ x  # leftunital_plus_int 1 
	axiom_rightUnitalPlus : {x : ℤ} ⊦ arithmetics?IntegerArithmetics?addition x 0 ≐ x  # rightunital_plus_int 1
	axiom_leftUnitalTimes : {x : ℤ} ⊦ 1 ⋅ x ≐ x  # leftunital_times_int 1 
	axiom_rightUnitalTimes : {x : ℤ} ⊦ x ⋅ 1 ≐ x  # rightunital_times_int 1 
	axiom_distributive : {x : ℤ, y : ℤ, z : ℤ} ⊦ arithmetics?IntegerArithmetics?multiplication x (arithmetics?IntegerArithmetics?addition y z) ≐ 
		arithmetics?IntegerArithmetics?addition (arithmetics?IntegerArithmetics?multiplication x y) (arithmetics?IntegerArithmetics?multiplication x z)  # distributive_int 1 2 3 

	
namespace http://mathhub.info/MitM/core/arithmetics 

import base http://mathhub.info/MitM/Foundation 

theory NaturalNumbers : base:?Logic =
	include ☞base:?NatLiterals 

	succ : ℕ ⟶ ℕ  # Succ 1 prec 5  = [n] succ_nat_lit n 

	axiom_succ1 : {x} ⊦ 0 ≠ Succ x 
	axiom_succ2 : {x:ℕ,y:ℕ} ⊦ Succ x ≐ Succ y ⟶ ⊦ x ≐ y 
	axiom_Induction: {A : ℕ ⟶ bool} ⊦ A 0 ⟶ ({x}⊦ A x ⟶ ⊦ A (Succ x)) ⟶ {x} ⊦ A x 


	
theory NaturalArithmetics : base:?Logic =
	include ?NaturalNumbers 
	include ☞base:?DescriptionOperator 

	/T Addition ❙
	addition : ℕ ⟶ ℕ ⟶ ℕ  # 1 + 2 prec 15  = plus_nat_lit 
	axiom_plus1 : {x} ⊦ x + 0 ≐ x  # axiom_plus1 
	axiom_plus2 : {x,y} ⊦ x + Succ y ≐ Succ (x + y) 
	
	/T Subtraction ❙
	subtraction : {n : ℕ, m : ℕ, p : ⊦ ∃! [x : ℕ] m + x ≐ n}ℕ  = [n,m,p] ι [x: ℕ] m + x ≐ n  # 1 - 2 %I3 prec 15 
	// TODO proof arguments are in the way ❙
	// theorem_sub1: ⊦ ∀[n] n - zero ≐ n ❙
	// theorem_sub2: ⊦ ∀[n] ∀[m] m ≤ n ⇒ (S n) - (S m) ≐ n - m ❙
	
	/T Multiplication ❙
	multiplication : ℕ ⟶ ℕ ⟶ ℕ  # 1  2 prec 25  = times_nat_lit 
	axiom_times1 : {x : ℕ} ⊦ x ⋅ 1 ≐ x 
	axiom_times2 : {x,y} ⊦ x ⋅ Succ y ≐ x + x ⋅ y 
	axiom_times3 : {x: ℕ} ⊦ x ⋅ 0 ≐ 0 ∧ 0 ⋅ x ≐ 0 
	
	/T Division ❙
	divides : ℕ ⟶ ℕ ⟶ bool  = [n,m] ∃! [r : ℕ] n ⋅ r ≐ m  # 1 | 2 prec 105 
	div : {n : ℕ, m : ℕ, p : ⊦ ∃! [r : ℕ] n ⋅ r ≐ m} ℕ  = [n,m,p] ι ([r : ℕ] n ⋅ r ≐ m)  # 1 / 2 %I3 prec 105 
	// theorem_div1: ⊦ ∀[n] ¬ (n ≐ 0) ⇒ zero / n ≐ zero ❙
	// theorem_div2: ⊦ ∀[n] ∀[m] ¬(m ≐ zero) ∧ (m | n) ⇒ n / m ≐ S ((n - m) / m) ❙
	
	/T Exponentiation ❙
	exponentiation : ℕ ⟶ ℕ ⟶ ℕ  # 1 ^ 2 prec 35 
	axiom_exp1 : {x} ⊦ x ^ 0 ≐ 1 
	axiom_exp2 : {x,y} ⊦ x ^ Succ y ≐ x ⋅ x ^ y 
	
	/T Roots ❙
	root : {n : ℕ, m : ℕ, p : ⊦ ∃![x] x^m ≐ n}ℕ  = [n,m,p] ι [x] x^m ≐ n   # 2  1 %I3 prec 35
	squareRoot : {n : ℕ, p : ⊦ ∃![m] m^2 ≐ n}ℕ  = [n,p] 2 √ n  #  1 %I2 prec 35 
	
	/T Order ❙
	leq : ℕ ⟶ ℕ ⟶ bool  = [n,m] ∃! [x] n + x ≐ m  # 1  2 prec 105 
	geq : ℕ ⟶ ℕ ⟶ bool  = [n,m] m ≤ n  # 1  2 prec 105 
	lessthan : ℕ ⟶ ℕ ⟶ bool  = [n,m] n ≤ m ∧ n ≠ m  # 1 < 2 prec 105 
	morethan : ℕ ⟶ ℕ ⟶ bool  = [n,m] n ≥ m ∧ n ≠ m  # 1 > 2 prec 105 
	
	/T Others ❙
	max : ℕ ⟶ ℕ ⟶ ℕ  # max 1 2 
	min : ℕ ⟶ ℕ ⟶ ℕ  # min 1 2 
	
	mod : ℕ ⟶ ℕ ⟶ ℕ  # 1 mod 2 prec 25 
	// axiom_mod1: ⊦ ∀[n] ∀[m] n < m ⇒ (n mod m) ≐ n ❙
	// axiom_mod2: ⊦ ∀[n] ∀[m] (m ≤ n) ⇒ ((n mod m) ≐ ((n - m) mod m)) ❙

	primes : type  = ⟨ x : ℕ+ | ⊦ x ≠ 1 ∧ ∀ [y : ℕ] (y | x) ⇒ (y ≐ 1 ∨ y ≐ x) ⟩ 
	fromOneTo : ℕ+ ⟶ type  = [n] ⟨ x: ℕ+ | ⊦ 1 ≤ x ∧ x ≤ n ⟩ 
	
	/T Monoid Axioms ❙
	axiom_associativePlus : {x: ℕ,y,z} ⊦ x + (y + z) ≐ (x + y) + z  # associative_plus_nat 1 2 3
	axiom_leftUnitalPlus : {x : ℕ} ⊦ 0 + x ≐ x  # leftunital_plus_nat 
	lemma_rightUnitalPlus : {x : ℕ} ⊦ x + 0 ≐ x  = axiom_plus1  # rightunital_plus_nat 
	

	
namespace http://mathhub.info/MitM/core/arithmetics 

import base http://mathhub.info/MitM/Foundation 

theory RationalNumbers : base:?Logic =
	include ?IntegerNumbers 
	
	rationalNumbers : type  #  
	axiom_intsAreRats : int_lit <* ℚ 
	axiom_natsAreRats : nat_lit <* ℚ 
	axiom_natsAreRats2 : NAT <* ℚ 
	axiom_posAreRats : pos_lit <* ℚ 

	fraction : ℤ ⟶ ℕ+ ⟶ ℚ  # 1/2 
	// TODO: this is the constructor ❙

	
theory RationalArithmetics : base:?Logic =
	include ?IntegerArithmetics 
	include ?RationalNumbers 
	
	/T Negation ❙
	uminus : ℚ ⟶ ℚ  # - 1 prec 33 
	axiom_ratUminusIsIntUminus : {x : ℤ} ⊦ arithmetics?RationalArithmetics?uminus x ≐ arithmetics?IntegerArithmetics?uminus x  

	/T Addition ❙
	addition : ℚ ⟶ ℚ ⟶ ℚ  #  1 + 2 prec 13 
	axiom_ratPlusIsIntPlus : {x : ℤ, y : ℤ} ⊦ arithmetics?RationalArithmetics?addition x y ≐ arithmetics?IntegerArithmetics?addition x y  
	axiom_plusUminus : {x : ℚ} ⊦ x + (-x) ≐ 0  role Simplify 
	
	/T Subtraction ❙
	subtraction : ℚ ⟶ ℚ ⟶ ℚ  = [a,b] a + (-b)  # 1 - 2 prec 13 
	
	/T Multiplication ❙
	multiplication : ℚ ⟶ ℚ ⟶ ℚ  #  1  2 prec 23 
	axiom_ratTimesIsNatTimes : {x : ℤ, y : ℤ} ⊦ arithmetics?RationalArithmetics?multiplication x y ≐ arithmetics?IntegerArithmetics?multiplication x y 

	/T Division ❙
	non_zero_rationals = ⟨ x : ℚ | ⊦ x ≠ 0 ⟩  # ℚ*
	inverse : {x:ℚ, p:⊦ x ≠ 0} ℚ  # inv 1 %I2 prec 33 
	inverseTyped : ℚ* ⟶ ℚ* 
	axiom_inv : {r : ℚ, p: ⊦ r ≠ 0} ⊦ r ⋅ (inv r) ≐ 1  //  role Simplify  # Axiom_inv_rat 1 2 
	axiom_inv2 : {r : ℚ* } ⊦ r ⋅ (inverseTyped r) ≐ 1  # axiom_inv2 
	div : {r:ℚ,s:ℚ, p:⊦ s ≠ 0} ℚ  = [r,s,p] r ⋅ (inv s)  # 1 / 2 %I3 prec 6 
	
	/T Exponentiation ❙
	exponentiation : ℚ ⟶ ℚ ⟶ ℚ  #  1 ^ 2 prec 33 
	axiom_ratExpIsNatExp : {x : ℤ, y : ℤ} ⊦ arithmetics?RationalArithmetics?exponentiation x y ≐ arithmetics?IntegerArithmetics?exponentiation x y 
	
	/T Roots ❙
	root : {n : ℚ, m : ℕ, p : ⊦ ∃![x] x^m ≐ n}ℚ  = [n,m,p] ι [x] x^m ≐ n   # 2  1 %I3 prec 33 
	squareRoot : {n : ℚ, p : ⊦ ∃![m] m^2 ≐ n}ℚ  = [n,p] 2 √ n  #  1 %I2 prec 33 
	
	/T Orders ❙
	leq : ℚ ⟶ ℚ ⟶ bool  # 1  2 prec 103 
	geq : ℚ ⟶ ℚ ⟶ bool  = [n,m] m ≤ n  # 1  2 prec 103 
	lessthan : ℚ ⟶ ℚ ⟶ bool  = [n,m] n ≤ m ∧ n ≠ m  # 1 < 2 prec 103 
	morethan : ℚ ⟶ ℚ ⟶ bool  = [n,m] n ≥ m ∧ n ≠ m  # 1 > 2 prec 103 
	max : ℚ ⟶ ℚ ⟶ ℚ  # max 1 2 
	min : ℚ ⟶ ℚ ⟶ ℚ  # min 1 2 
	axiom_ratLeqIsIntLeq : {x : ℤ, y : ℤ} ⊦ arithmetics?RationalArithmetics?leq x y ≐ arithmetics?IntegerArithmetics?leq x y 
	
	/T Others ❙
	absolute : ℚ ⟶ ℚ  = [q] case q < 0 ⟹ -q . q  # | 1 | prec 9 
	
	/T Field axioms ❙
	axiom_associativePlus : {x: ℚ,y,z} ⊦ x + (y + z) ≐ (x + y) + z  # associative_plus_rat 1 2 3
	axiom_associativeTimes : {x: ℚ,y,z} ⊦ x ⋅ (y ⋅ z) ≐ (x ⋅ y) ⋅ z  # associative_times_rat 1 2 3 
	axiom_leftUnitalPlus : {x : ℚ} ⊦ arithmetics?RationalArithmetics?addition 0 x ≐ x  # leftunital_plus_rat 1 
	axiom_rightUnitalPlus : {x : ℚ} ⊦ arithmetics?RationalArithmetics?addition x 0 ≐ x  # rightunital_plus_rat 1
	axiom_leftUnitalTimes : {x : ℚ} ⊦ 1 ⋅ x ≐ x  # leftunital_times_rat 1 
	axiom_rightUnitalTimes : {x : ℚ} ⊦ x ⋅ 1 ≐ x  # rightunital_times_rat 1 
	axiom_distributive : {x : ℚ, y : ℚ, z : ℚ} ⊦ x ⋅ (y + z) ≐ (x ⋅ y) + (x ⋅ z)  # distributive_rat 1 2 3 
	axiom_commutativePlus : {x : ℚ,y} ⊦ x + y ≐ y + x  # addition_commutative_rat 1 2 
	axiom_commutativeTimes : {x : ℚ,y} ⊦ x ⋅ y ≐ y ⋅ x  # times_commutative_rat 1 2 

namespace http://mathhub.info/MitM/core/arithmetics 

import base http://mathhub.info/MitM/Foundation 

theory RealNumbers : base:?Logic =
	include ☞base:?RealLiterals 
	include ?RationalNumbers 
	RealNumbers = 
	axiom_ratsAreReal : ℚ <* ℝ 
	axiom_intsAreReal : ℤ <* ℝ 
	axiom_natsAreReal : ℕ <* ℝ 
	axiom_posAreReal : ℕ+ <* ℝ 
	NAT_is_real : NAT <* ℝ 


theory RealArithmetics : base:?Logic =
	include ?RealNumbers                                   
	include ?RationalArithmetics 
	
	/T Negation ❙
	uminus : ℝ ⟶ ℝ  # - 1 prec 32  = minus_real_lit 
	axiom_realMinusIsRatMinus : {x : ℚ} ⊦ arithmetics?RealArithmetics?uminus x ≐ arithmetics?RationalArithmetics?uminus x 
	
	/T Addition ❙
	addition : ℝ ⟶ ℝ ⟶ ℝ  #  1 + 2 prec 12  = plus_real_lit 
	axiom_realPlusIsRatPlus : {x : ℚ, y : ℚ} ⊦ arithmetics?RealArithmetics?addition x y ≐ arithmetics?RationalArithmetics?addition x y  
	axiom_plusUminus : {x : ℝ} ⊦ (x + (-x)) ≐ 0 
	
	/T Subtraction ❙
	subtraction : ℝ ⟶ ℝ ⟶ ℝ  = [a,b] a + (-b)  # 1 - 2 prec 12 
	
	/T Multiplication ❙
	multiplication : ℝ ⟶ ℝ ⟶ ℝ  #  1  2 prec 22  = times_real_lit 
	axiom_realTimesIsRatTimes : {x : ℚ, y : ℚ} ⊦ arithmetics?RealArithmetics?multiplication x y ≐ arithmetics?RationalArithmetics?multiplication x y 
	
	/T Division ❙
	no_zero_reals = ⟨ x : ℝ | ⊦ x ≠ 0 ⟩  # ℝ* 
	inverse : {x:ℝ, p:⊦ x ≠ 0} ℝ  # inv 1 %I2 prec 32 
	inverseTyped : ℝ* ⟶ ℝ*  # inverseTyped 1 prec -1 
	axiom_inv : {x : ℝ, p : ⊦ x ≠ 0} ⊦ x ⋅ (inv x) ≐ 1 
	axiom_inv2 : {r : ℝ* } ⊦ r ⋅ (inverseTyped r) ≐ 1  # axiom_inv2 
	div : {r:ℝ,s:ℝ, p:⊦ s ≠ 0} ℝ  = [r,s,p] r ⋅ (inv s)  # 1 / 2 %I3 prec 5 

	/T Exponentiation ❙
	exponentiation : ℝ ⟶ ℝ ⟶ ℝ  #  1 ^ 2 prec 32 
	axiom_realExpIsRatExp: {x : ℚ, y : ℚ} ⊦ arithmetics?RealArithmetics?exponentiation x y ≐ arithmetics?RationalArithmetics?exponentiation x y 
	
	/T Roots ❙
	root : {n : ℝ, m : ℕ, p : ⊦ ∃![x] x^m ≐ n}ℝ  = [n,m,p] ι [x] x^m ≐ n   # 2  1 %I3 prec 32 
	squareRoot : {n : ℝ, p : ⊦ ∃![m] m^2 ≐ n}ℝ  = [n,p] 2 √ n  #  1 %I2 prec 32 
	
	/T Order ❙
	leq : ℝ ⟶ ℝ ⟶ bool  # 1  2 prec 102 
	geq : ℝ ⟶ ℝ ⟶ bool  = [n,m] m ≤ n  # 1  2 prec 102 
	lessthan : ℝ ⟶ ℝ ⟶ bool  = [n,m] n ≤ m ∧ n ≠ m  # 1 < 2 prec 102 
	morethan : ℝ ⟶ ℝ ⟶ bool  = [n,m] n ≥ m ∧ n ≠ m  # 1 > 2 prec 102 
	max : ℝ ⟶ ℝ ⟶ ℝ  # max 1 2 
	min : ℝ ⟶ ℝ ⟶ ℝ  # min 1 2 
	axiom_realLeqIsRatLeq : {x : ℚ, y : ℚ} ⊦ arithmetics?RealArithmetics?leq x y ≐ arithmetics?RationalArithmetics?leq x y 
	
	/T Subtypes ❙
	NonNegativeRealNumbers : type  # ℝ^+  = ⟨ x : ℝ | ⊦ x ≥ 0 ⟩
	PositiveRealNumbers : type  # ℝ+  = ⟨ x : ℝ | ⊦ x > 0 ⟩
	
	/T Suprema ❙
	// to allow for later usage of subspaces by way of a boolean function that tells whether it is part of the domain or not ❙
	predAsSub : (ℝ ⟶ bool) ⟶ type  = [P] ⟨ z : ℝ | ⊦ P z ⟩  # pred 1 
	sup : (ℝ ⟶ bool) ⟶ ℝ 
	axiom_sup1 : {P : ℝ ⟶ bool, y : pred P} ⊦ y ≤ sup P 
	axiom_sup2 : {P : ℝ ⟶ bool, y : ℝ, p : {z: pred P}⊦z ≤ y} ⊦ sup P ≤ y 
	
	/T Others ❙
	absolute : ℝ ⟶ ℝ^+  // = [q] case q < 0 ⟹ -q . q  # | 1 | prec 8 
	
	/T Field Axioms ❙
	axiom_associativePlus : {x: ℝ,y,z} ⊦ x + (y + z) ≐ (x + y) + z  # associative_plus_real 1 2 3
	axiom_associativeTimes : {x: ℝ,y,z} ⊦ x ⋅ (y ⋅ z) ≐ (x ⋅ y) ⋅ z  # associative_times_real 1 2 3 
	axiom_leftUnitalPlus : {x : ℝ} ⊦ 0 + x ≐ x  # leftunital_plus_real 1 
	axiom_rightUnitalPlus : {x : ℝ} ⊦ x + 0 ≐ x  # rightunital_plus_real 1
	axiom_leftUnitalTimes : {x : ℝ} ⊦ 1 ⋅ x ≐ x  # leftunital_times_real 1 
	axiom_rightUnitalTimes : {x : ℝ} ⊦ x ⋅ 1 ≐ x  # rightunital_times_real 1 
	axiom_distributive : {x : ℝ, y, z} ⊦ x ⋅ (y + z) ≐ (x ⋅ y) + (x ⋅ z)  # distributive_real 1 2 3 
	axiom_commutativePlus : {x : ℝ,y} ⊦ x + y ≐ y + x  # addition_commutative_real 1 2 
	axiom_commutativeTimes : {x : ℝ,y} ⊦ x ⋅ y ≐ y ⋅ x  # times_commutative_real 1 2 


theory ExtendedReals : base:?Logic =
	include ?RealArithmetics 
	// extended_reals : type ❘ # ℝ∞ ❙ 
	// reals_are_extended : ℝ <* ℝ∞ ❙ 
	infty :  #  prec 1 
	// leq : ℝ∞ ⟶ ℝ∞ ⟶ bool ❘ # 1 ≤ 2 prec 101 ❙
	// TODO neginfty : ℝ∞ ❘ = - ∞ ❘ # -∞ ❙

namespace  http://mathhub.info/MitM/core/calculus 


import base http://mathhub.info/MitM/Foundation 
import arith http://mathhub.info/MitM/core/arithmetics 

theory FinSequences : base:?Logic =
	include ☞arith:?NaturalArithmetics 
	below : ℕ ⟶ type  = [n] ⟨ x : ℕ | ⊦ x < n ⟩ 
	toBelow : {n : ℕ} below (Succ n) # toB 1 
	succBelow : {n : ℕ} below n ⟶ below (Succ n) # succB 2

	belowIsSubtypeOfNat : {n : ℕ} (below n) <* ℕ 


	belowToNat : {n : ℕ} below (Succ n) ⟶ ℕ # btn 1 2
	belowToNatBaseCase : {m : ℕ} ⊦ belowToNat m (toBelow m) ≐ m
    belowToNatRecCase : {m : ℕ, b : below (Succ m)} ⊦ belowToNat (Succ m) (succBelow (Succ m) b) ≐ belowToNat m b 
  
    belowToNatExample : ⊦ btn 3 (toB 3) ≐ 3
    belowToNatExample2 : ⊦ btn 4 (succB (toB 3)) ≐ 3 
	belwoToNatExample2_2 : ⊦ belowToNat (Succ 3) (succBelow (Succ 3) (toBelow 3)) ≐ 3
	
//	belowToNat2 : {n : ℕ} below (Succ  n) ⟶ ℕ ❘= [n, b] n ❘# btn2 %I1 ❙
//	belowToNat3 : {n : ℕ, m : ℕ} below n ⟶ ⊦ m < n ⟶ ℕ ❘= [n , m , b, p ] m ❘#  btn3 %I1 ❙
//	belowToNat4 : {n : ℕ} below n ⟶ ⟨ ℕ | [x] ⊦ x < n⟩ ❘# btn4 %I1❙


	finSeq : ℕ ⟶ type ⟶ type = [n , A] below n ⟶ A  

	
	nonEmptyFinSeq_prop : {n : ℕ, A : type} finSeq n A ⟶ bool = [n, A , f] 0 < n # nefs %I1 %I2 
	
	disjointFinSeq_prop : {n : ℕ, A : type} finSeq n A ⟶ bool
	disjointFinSeq_prop_trivial :  {A : type,f : finSeq 0 A} ⊦ disjointFinSeq_prop 0 A f ≐ true
	disjointFinSeq_prop_step // : {A : type , n : ℕ , f : 
			finSeq (succ n) A} ⊦ disjointFinSeq_prop (succ n) A f ≐ ∀ [m1 : below (succ n)] ∀ [m2 : below (succ n)] ⊦ m1 ≠ m2 ⟶ ⊦ true 
	belowShift : {n : ℕ , m : ℕ} below n ⟶ below (n + m)
//	belowShift_base : {n, b} ⊦ belowShift n 0 b ≐ b❙ 
	
//	finSeqSum : {n : ℕ , b : below n} ❙

namespace http://mathhub.info/MitM/core/calculus 

import base http://mathhub.info/MitM/Foundation 
import arith http://mathhub.info/MitM/core/arithmetics 

theory SimpleDerivatives : base:?Logic =
   include ?RealMetricSpace 
   include ☞base:?NaturalDeduction 
   include ?FunctionLimit 
   
   axiom_neqImplNotZero : {a : ℝ, b : ℝ} ⊦ neq ℝ a b ⟶ ⊦ neq ℝ (b - a) 0  # idnz 3 
   
   differenceQuotient : {P : ℝ ⟶ bool, f: pred P ⟶ ℝ, a: pred P}{x : pred P, p:⊦ neq ℝ a x}ℝ 
   		= [P,f,a : pred P] ([x : pred P,p] ☞arith:?RealArithmetics?div ((f x) - (f a)) (x - a) (idnz p)) 
   
   prop_differentiableAt : {P : ℝ ⟶ bool}(pred P ⟶ ℝ) ⟶ pred P ⟶ prop 
   		= [P,f,a] prop_hasLimit_c (mpred P) ℝm ([x: pred P] neq ℝ a x) ([x,p] differenceQuotient P f a x p) a 
   	
   prop_differentiable : {P : ℝ ⟶ bool}(pred P ⟶ ℝ) ⟶ prop  # diff 2 
   		= [P,f] ∀ [x : pred P] prop_differentiableAt P f x 
   		
   /T derivative: P as predicate of where derivative is defined, f as a function on P of value ℝ, p as the proof that f is differentiable on P❙		
   derivative : {P : ℝ ⟶ bool,f : pred P ⟶ ℝ, p : ⊦ diff f} pred P ⟶ ℝ 
   		= [P,f,p][a] limit_c (mpred P) ℝm ([x: pred P] neq ℝ a x) ([x,q] differenceQuotient P f a x q) a (forall_elim (pred P) ([x : pred P] prop_differentiableAt P f x) p a)  # 2 ' %I3 
   		// defined as the limit of the diff_quotient on p, giving a proof that it is differentiable on P ❙
   	
   	f : pred ([x] true) ⟶ ℝ 
   	

 
   
namespace http://mathhub.info/MitM/core/calculus 

import top http://mathhub.info/MitM/core 
import base http://mathhub.info/MitM/Foundation 

import meta http://cds.omdoc.org/mmt 

//   author: Theresa Pollinger ❚
 
 
//   a lot of stuff here stolen from dgls.mmt xx: 
//   To not make things too awful, I've now fixed one ⋁ for a vectorspace; just for notational reasons. ❚

//   as "domains" is overloaded between disciplines: in numerical modeling, we are talking about finite, (singly) connected subspaces of ℝ^n as domains ❚

theory Intervals : base:?Logic = 
	include ☞top:/arithmetics?RealArithmetics 
	include ☞top:/algebra?RealField 
	include ?RealMetricSpace 

	theory interval_theory : base:?Logic =
		left : 
		right : 
		leftPred : ℝ ⟶ ℝ ⟶ prop 
		rightPred : ℝ ⟶ ℝ ⟶ prop 
		predicate : ℝ ⟶ prop  = [x] leftPred left x ∧ rightPred x right 
		tp : type  = pred predicate  
	
	
	interval : type  = Mod ☞?Intervals/interval_theory 
	
	closedInterval : ℝ ⟶ ℝ ⟶ interval  = [a,b] ['
		left := a,
		right := b,
		leftPred := ([x,y] x ≤ y),
		rightPred := ([x,y] x ≤ y)
	']  # [ 1 ; 2 ] 
	


theory OneCuboid : base:?Logic = 
	include ☞top:/arithmetics?RealArithmetics 

	theory oneCuboid_theory : base:?Logic =
		left : 
		right : 
		leftPred : ℝ ⟶ ℝ ⟶ prop 
		rightPred : ℝ ⟶ ℝ ⟶ prop 
		predicate : ℝ ⟶ prop  = [x] leftPred left x ∧ rightPred x right 
		tp : type  = pred predicate  
	
	
	interval : type  = Mod ☞?Intervals/interval_theory 
	
	closed1Cuboid : ℝ ⟶ ℝ ⟶ interval  = [a,b] ['
		left := a,
		right := b,
		leftPred := ([x,y] x ≤ y),
		rightPred := ([x,y] x ≤ y)
	']  # [ 1 ; 2 ] 
	


theory GeneralDomains : base:?Logic = 
  include ☞top:/arithmetics?NaturalNumbers 
  include ☞top:/algebra?RealField 
  include ?Ball 
  include ☞top:/algebra?Vectorspace 
  
  theory generalDomain_theory : base:?Logic =
  	 include ☞top:/algebra?Vectorspace/vectorspace_theory (realField) 
  	 include ?MetricSpace/metricSpace_theory 
  	 dimension : 
  	 domainPred : U ⟶ prop 
  	 domain : type  = ⟨ x : U | ⊦ domainPred x ⟩ 
  	 boundaryPred1 : U ⟶ prop  = [b] ∀ [ε : ℝ+] ∃[x : domain] d x b < ε 
  	 boundaryPred2 : U ⟶ prop  = [b] ∀ [ε : ℝ+] ∃[x : U] d x b < ε ∧ ¬ domainPred x 
  	 boundaryPred : U ⟶ prop  = [b] boundaryPred1 b ∧ boundaryPred2 b 
  	 boundary : type   = ⟨ x : U | ⊦ boundaryPred x ⟩ 
  
  	 
  generalDomain = Mod ☞?GeneralDomains/generalDomain_theory 
  

// view IntervalsAsDomains : ?GeneralDomains/generalDomain_theory ⟶ ?Intervals/interval_theory =
    = ℝ ❙ 
   // Dimension = 1 ❙
   DomainPred = interval_pred ❙
   BoundaryPred = boundary_pred ❙
   // vec_pred_as_sub = pred_as_sub ❙
 
namespace http://mathhub.info/MitM/core/calculus 

import base http://mathhub.info/MitM/Foundation 
import ts http://mathhub.info/MitM/core/typedsets 
import ms http://mathhub.info/MitM/core/measures 

theory LebesgueIntegral : base:?Logic =
	include ☞ms:?Measure 
	include ☞ts:?Functions 
	include ☞ts:?SetCollection 
	include ?SimpleFunctions 
	include ☞ts:?SetSum 
	include ☞ts:?SupremumReal 
	include ☞ms:?LebesgueMeasurable 
	// include arith:?RealArithmetics ❙

  simpleLebesgueIntegral :  {m : measureSpace , s : nonnegativeSimpleFunction  m }  ℝ 
    = [m , s] setSum  ((im (πl s) (fullset (m.universe))) : set ℝ) 
  (theorem_nonnegativeSimpleFunctionHasFiniteValues m s) (([x] x ⋅ (m.rmeasure.measure) (elem (m.sigma_algebra.coll) (preim (πl s) (single x)))) : ℝ ⟶ ℝ) 
	
  upperFunction : {a : type} (a ⟶ ℝ) ⟶ a ⟶ ℝ  =  [a , f , x ] max (f x) 0
  
  lowerFunction : {a : type} (a ⟶ ℝ) ⟶ a ⟶ ℝ  =  [a : type, f : a ⟶ ℝ, x : a] max (- f x) 0  
  
  lemma_upperFunctionIsNonNegative : {A : type , f : A ⟶ ℝ} ⊦ prop_nonnegative_function (upperFunction A f) 
  # upperFunctionIsNonNegative 2
  
  lemma_lowerFunctionInNonNegative : {A : type , f : A ⟶ ℝ} ⊦ prop_nonnegative_function (lowerFunction A f)  
  # lowerFunctionInNonNegative 2
  
 
	positiveLebesgueIntegral : {m : measureSpace, f : (m.universe ⟶ ℝ)} ⊦ lebesgueMeasurableLeq (m.sigma_algebra) f ⟶
	⊦ prop_nonnegative_function f  ⟶ ℝ 
	 = [m , f, p1,p2] supR ( im (simpleLebesgueIntegral m) ( ⟪ fullset (nonnegativeSimpleFunction m) | ([ff] (∀[x] ((πl ff) x) ≤ (f x))) ⟫ )) 

	
	lemma_lebesgueMeasurableFunctionUpperLebesgueMeasurable : 
	{A : type , s : sigmaAlgebra A, f : A ⟶ ℝ} ⊦ lebesgueMeasurableLeq s f ⟶ ⊦ lebesgueMeasurableLeq s (upperFunction A f)  
	 # lebesgueMeasurableFunctionUpperLebesgueMeasurable 2 3 4
	
	lemma_lebesgueMeasurableFunctionLowerLebesgueMeasurable : 
	{A : type , s : sigmaAlgebra A, f : A ⟶ ℝ} ⊦ lebesgueMeasurableLeq s f ⟶ ⊦ lebesgueMeasurableLeq s (lowerFunction A f)  
	# lebesgueMeasurableFunctionLowerLebesgueMeasurable 2 3 4
	
	lebesgueIntegrable : {ms : measureSpace, f : (ms.universe ⟶ ℝ)} ⊦ lebesgueMeasurableLeq (ms.sigma_algebra) f ⟶ bool
	 = [ms, f , p] positiveLebesgueIntegral ms (upperFunction (ms.universe) f) 
	(lebesgueMeasurableFunctionUpperLebesgueMeasurable (ms.sigma_algebra) f p) 
	(upperFunctionIsNonNegative f)
	< ∞ ∧ positiveLebesgueIntegral ms (lowerFunction (ms.universe) f) 
	(lebesgueMeasurableFunctionLowerLebesgueMeasurable (ms.sigma_algebra) f p) 
	(lowerFunctionInNonNegative f)
	< ∞ 
	

	quasiIntegrable : {ms : measureSpace , f : (ms.universe ⟶ ℝ)} ⊦ lebesgueMeasurableLeq (ms.sigma_algebra) f ⟶ bool 
	 = [ms, f , p] positiveLebesgueIntegral ms (upperFunction (ms.universe) f) 
	(lebesgueMeasurableFunctionUpperLebesgueMeasurable (ms.sigma_algebra) f p) 
	(upperFunctionIsNonNegative f)
	< ∞ ∨ positiveLebesgueIntegral ms (lowerFunction (ms.universe) f) 
	(lebesgueMeasurableFunctionLowerLebesgueMeasurable (ms.sigma_algebra) f p) 
	(lowerFunctionInNonNegative f)
	< ∞ 
	

	lebesgueIntegral : {m : measureSpace ,f : ((m.universe ⟶ ℝ)) , 
	p1 : ⊦ lebesgueMeasurableLeq (m.sigma_algebra) f}  ⊦  quasiIntegrable m f p1 ⟶ ℝ   
	 = [m,f, p1 , p2] 
	(positiveLebesgueIntegral m (upperFunction (m.universe) f) 
	(lebesgueMeasurableFunctionUpperLebesgueMeasurable (m.sigma_algebra) f p1) 
	(upperFunctionIsNonNegative f) : ℝ) + 
	(- (positiveLebesgueIntegral m (lowerFunction (m.universe) f) 
	(lebesgueMeasurableFunctionLowerLebesgueMeasurable (m.sigma_algebra) f p1) 
	(lowerFunctionInNonNegative f) : ℝ))
	
	


namespace http://mathhub.info/MitM/core/calculus 

import base http://mathhub.info/MitM/Foundation 
import ts http://mathhub.info/MitM/core/typedsets 
import ms http://mathhub.info/MitM/core/measures 

theory SimpleFunctions : base:?Logic = 
	include ☞ms:?Measure 
	include ☞ts:?Functions 
	include ☞ms:?PowerSigmaAlgebra 
	include ☞ms:?BorelMeasurable 
//	include top:?RealTopology ❙
	
	
	prop_nonnegative_function : {A : type} (A ⟶ ℝ) ⟶ bool = [A , f] ∀ [x : A] (0 : ℝ) ≤ ((f x) : ℝ) # prop_nonnegative_function 2  
	prop_simpleFunction  : {m : measurableSpace } (m.universe ⟶ ℝ) ⟶ bool 
	 = [m , f] (im f (fullset (m.universe))) finite ∧ 
	(∀ [x]  x ∈ im f (fullset m.universe) ⇒ preim f (single x)  ∈ (m.sigma_algebra.coll)) 
	
	simpleFunction : measurableSpace ⟶ type = [m] Σ f : (m.universe ⟶ ℝ) . ⊦ prop_simpleFunction m f    
	nonnegativeSimpleFunction : measurableSpace ⟶ type  = [m] Σ f: (m.universe ⟶ ℝ) . ⊦ prop_simpleFunction m f  ∧ prop_nonnegative_function f  

	simpleFunctionIsMeasurable : {m1 : measurableSpace  , f : simpleFunction m1} ⊦ measurable (m1.sigma_algebra) (powerSigmaAlgebra ℝ) (πl f) 
	simpleFunctionIsBorelMeasurable : { m : measurableSpace , s : simpleFunction m} 
	⊦  realBorelMeasurable (m.universe) (m.sigma_algebra) (πl s) 
	
	
	theorem_simpleFunctionHasFiniteValues : {m : measurableSpace, S : simpleFunction m} ⊦ (im (πl S) (fullset (m.universe))) finite # simpleFunctionHasFiniteValues 1 2 
	theorem_nonnegativeSimpleFunctionHasFiniteValues : {m : measurableSpace, S : nonnegativeSimpleFunction m} ⊦ (im (πl S) (fullset (m.universe))) finite # nonnegativeSimpleFunctionHasFiniteValues 1 2 
	
	
                                                                                 
namespace http://mathhub.info/MitM/core/calculus 

import base http://mathhub.info/MitM/Foundation 
import sets http://mathhub.info/MitM/core/typedsets 
import algebra http://mathhub.info/MitM/core/algebra 
import topo http://mathhub.info/MitM/core/topology 

theory MetricSpace : base:?Logic = 
   include arithmetics?RealArithmetics 
   include ☞sets:?SetStructures 
   
	theory signature_theory : base:?Logic =
		include ☞sets:?SetStructures/setstruct_theory 
		d : U ⟶ U ⟶ ℝ 
	
	signature = Mod ☞?MetricSpace/signature_theory 
   
	prop_nonNegative :  {G : type, d : G ⟶ G ⟶ ℝ} prop  = [G,d] ∀[x]∀[y] 0 ≤ d x y  
	prop_identityOfIndiscernibles :  {G : type, d : G ⟶ G ⟶ ℝ} prop  = [G,d] ∀[x]∀[y] d x y ≐ 0 ⇒ x ≐ y     
	prop_positiveDefinite : {G : type, d : G ⟶ G ⟶ ℝ^+ }prop  = [G,d] prop_nonNegative G d ∧ prop_identityOfIndiscernibles G d 
	prop_symmetric :  {G : type, d : G ⟶ G ⟶ ℝ} prop 
		= [G][d] ∀[x]∀[y]  d x y  ≐ d y x  
		
	prop_pseudoMetric : {G : type, d : G ⟶ G ⟶ ℝ^+} prop  = [G,d] prop_positiveDefinite G d ∧ prop_symmetric G d 
		
	theory pseudoMetricSpace_theory : base:?Logic =
		include ☞sets:?SetStructures/setstruct_theory 
		d : U ⟶ U ⟶ ℝ^+ 
		axiom_isPseudoMetric : ⊦ prop_pseudoMetric U d 
	
	pseudoMetricSpace = Mod ☞?MetricSpace/pseudoMetricSpace_theory 
	
	prop_triangleInequality :  {G : type, d : G ⟶ G ⟶ ℝ} prop 
		= [G][d] ∀[x]∀[y]∀[z] (d x z)  ≤ ((d y x) + (d y z))  

	theory metricSpace_theory : base:?Logic =
		include ?MetricSpace/pseudoMetricSpace_theory 
		axiom_triangleInequality : ⊦ prop_triangleInequality U d 
	
	metricSpace = Mod ☞?MetricSpace/metricSpace_theory 
	// metricSpace : type ⟶ type  ❘ # metricSpace 1 ❙ // = [A] ⟨metricspace | ([G] ⊦ A ≐≐ G.universe)⟩❘
  
	distanceFunction : type ⟶ type ❘ = ⟨A ⟶ A ⟶ ℝ | ([x] ⊦ ∃[G: metricSpace] x ≐ G.d)⟩ ❘ # distanceFunction 1 ❙ 
	metric : {G: metricSpace} (G.universe ⟶ G.universe ⟶ ℝ)  # d 2 3  = [G][a][b] (G.d) a b 


theory MetricMonoid : base:?Logic =
	include ?MetricSpace 
	include algebra?Monoid
	
	theory metricMonoid_theory : base:?Logic =
		include algebra?Monoid/monoid_theory 
		include ?MetricSpace/metricSpace_theory 
	
	metricMonoid = Mod ☞?MetricMonoid/metricMonoid_theory 


theory Ball : base:?Logic = 
   include ?MetricSpace 
   include ☞sets:?AllSets 
   openBall : {M: metricSpace} M.universe ⟶ ℝ ⟶ set (M.universe) 
   = [M][a][ε] ⟪ (doms M) | ([x] (d x a) < ε) ⟫  # B_ 3 2
   closedBall : {M: metricSpace} M.universe ⟶ ℝ ⟶ set (M.universe) 
   = [M][a][ε] ⟪ (doms M) | ([x] (d x a) ≤ ε) ⟫  // MiKo: how to do \overline{B} in the notation? ❙


theory MetricSpaceAsTopology : base:?Logic =
	include ?Ball 
	include ☞topo:?HausdorffTopology 
	// Why only Hausdorff? Don't we obtain even stronger conditions (normal?)? ❙
	// A: as soon as we formalized those, sure :) ❙
	openColl : {M : metricSpace} set (set (dom M)) 
	axiom_ballIsOpen : {M : metricSpace, a : M.universe, ε : ℝ} ⊦ (openBall M a ε) ∈ (openColl M) 
	
	axiom_emptyIsOpen : {M : metricSpace} ⊦ prop_emptyInColl (openColl M)  # emptyisopen 1 
	axiom_fullIsOpen : {M : metricSpace} ⊦ prop_fullInColl (openColl M)  # fullisopen 1 
	axiom_unionIsOpen : {M : metricSpace} ⊦ prop_unionInColl (openColl M)  # unionisopen 1 
	axiom_intersectionIsOpen : {M : metricSpace} ⊦ prop_finiteIntersection (openColl M)  # intersectionisopen 1 
	
	axiom_metricIsHausdorff : {M : metricSpace} ⊦ hausdorffProperty (dom M) (openColl M)  # miHaus 1 
	metricAsTopology : {M : metricSpace}hausdorffTopology (dom M)  
		= [M] [' 
			universe := M.universe, 
			d := M.d,
			axiom_isPseudoMetric := M.axiom_isPseudoMetric,
			axiom_triangleInequality := M.axiom_triangleInequality,
			coll := openColl M,
			axiom_empty := axiom_emptyIsOpen M,
			axiom_full := axiom_fullIsOpen M,
			☞?OML?axiom_union := axiom_unionIsOpen M,
			axiom_intersection := axiom_intersectionIsOpen M,
			ishausdorff := miHaus M
		'] 

  
theory RealMetricSpace : base:?Logic =
   include arithmetics?RealArithmetics 
   include ?MetricSpace 
   
   realmetric : ℝ ⟶ ℝ ⟶ ℝ^+  = [a,b] | a - b |  # ds 1 , 2 
   axiom_realIsPseudoMetric : ⊦ prop_pseudoMetric ℝ realmetric 
   axiom_triangleReal : ⊦ prop_triangleInequality ℝ realmetric 

   realmetricspace : metricSpace 
   		= [' 
   			universe := ℝ, 
   			d := realmetric, 
   			axiom_isPseudoMetric := axiom_realIsPseudoMetric,
   			axiom_triangleInequality := axiom_triangleReal
   		']  # ℝm    
   		
   	
   axiom_predRealIsPseudoMetric : {P : ℝ ⟶ bool} ⊦ prop_pseudoMetric (pred P) realmetric   # pseudom 1 
   axiom_predTriangle : {P : ℝ ⟶ bool} ⊦ prop_triangleInequality (pred P) realmetric  # realmet 1 
   
   realSubMetric : {P : ℝ ⟶ bool} metricSpace 
   		= [P] [' 
   			universe := pred P, 
   			d := [a : pred P][b : pred P] realmetric a b,
   			axiom_isPseudoMetric := pseudom P,
   			axiom_triangleInequality := realmet P
   		']  # mpred 1 
   		
   axiom_mpredIsSuptype : {P : ℝ ⟶ bool} (mpred P).universe <* ℝ 

namespace http://mathhub.info/MitM/core/calculus 

import base http://mathhub.info/MitM/Foundation 
import sets http://mathhub.info/MitM/core/typedsets 

theory Sequences : base:?Logic =
   include ?MetricSpace 
   include ☞sets:?AllSets 
   // MiKo: should G here not be a metric space? ❙
   sequence : {G: type}type  = [G] ℕ ⟶ G  # 1  prec 1 
   structseq : {G : setstruct}type  = [G] (G.universe)^ω  # 1 
   
   // prop_isSupremum : {G: metricSpace} G^ω ⟶ G.universe ⟶ prop  ❘
   		= [G,a,l] ∀[ε : ℝ+] (∀[n : ℕ] a n < l + ε) ∧ (∃[n : ℕ] a n > l - ε) ❙
   // prop_isInfimum : {G: metricSpace} G^ω ⟶ G.universe ⟶ prop  ❘
   		= [G,a,l] ∀[ε : ℝ+] (∀[n : ℕ] a n > l - ε) ∧ (∃[n : ℕ] a n < l + ε) ❙
   // prop_hasSupremum : {G: metricSpace} G^ω ⟶ prop  ❘
   		= [G,a] ∃![g] prop_isSupremum G a g   ❙
   // prop_hasInfimum : {G: metricSpace} G^ω ⟶ prop  ❘
   		= [G,a] ∃![g] prop_isInfimum G a g    ❙
   // supremum : {G : metricSpace, a : G^ω, p : ⊦ prop_hasSupremum G a} dom G ❘
   		= [G, a, p] that (dom G) ([g] prop_isSupremum G a g) p ❘
   		# sup 2 %I3 ❙
   // infimum : {G : metricSpace, a : G^ω, p : ⊦ prop_hasInfimum G a} dom G ❘
   		= [G, a, p] that (dom G) ([g] prop_isInfimum G a g) p ❘
   		# inf 2 %I3 ❙
   	// All of this stuff is only applicable to the real numbers, due to the usage of orders, addition etc. directly on elements of the
   		domain. Possibly can be generalized ❙


theory SequenceConvergence : base:?Logic =
	include ?Sequences 

	prop_converges : {G: metricSpace} G^ω ⟶ G.universe ⟶ prop  
		= [G,a,l] ∀[ε : ℝ+]∃[n : ℕ] ∀[m : ℕ] (m ≥ n) ⇒ (d (a m) l) < ε 
	prop_convergent : {G: metricSpace} G^ω ⟶ prop  
		= [G,a] ∃![g] prop_converges G a g   
            
	// isLimitSupremum : {G: metricSpace} G^ω ⟶ G.universe ⟶ prop  ❘
		// = [G,a,l] ∀[ε : ℝ+] (∀[N : ℕ] ∃[n : ℕ] (n ≥ N) ∧ (a n > l - ε)) ∧ (∃[N : ℕ] ∀[n : ℕ] (n ≥ N) ⇒ (a n < l + ε)) ❙
	// isLimitInfimum : {G: metricSpace} G^ω ⟶ G.universe ⟶ prop  ❘
		//  = [G,a,l] ∀[ε : ℝ+] (∀[N : ℕ] ∃[n : ℕ] (n ≥ N) ∧ (a n < l + ε)) ∧ (∃[N : ℕ] ∀[n : ℕ] (n ≥ N) ⇒ (a n > l - ε)) ❙
	// hasLimitSupremum : {G: metricSpace} G^ω ⟶ prop  ❘
		// = [G,a] ∃![g] isLimitSupremum G a g   ❙
	// hasLimitInfimum : {G: metricSpace} G^ω ⟶ prop  ❘
		// = [G,a] ∃![g] isLimitInfimum G a g    ❙
	// limitSupremum : {G : metricSpace, a : G^ω, p : ⊦ hasLimitSupremum G a} dom G ❘
		//   = [G, a, p] that (dom G) ([g] isLimitSupremum G a g) p ❘
		// # limsup 2 %I3 ❙
	// limitInfimum : {G : metricSpace, a : G^ω, p : ⊦ hasLimitInfimum G a} dom G ❘
		//  = [G, a, p] that (dom G) ([g] isLimitInfimum G a g) p ❘
		// # liminf 2 %I3 ❙
         
	prop_isLimit : {G: metricSpace} G^ω ⟶ G.universe ⟶ prop  
		= [G,a,l] ∀[ε : ℝ+] ∀[N : ℕ] ∃[n : ℕ] (n ≥ N) ∧ ((d (a n) l) < ε) 
	prop_hasLimit : {G: metricSpace} G^ω ⟶ prop  
		= [G,a] ∃![g] prop_isLimit G a g    
	limit : {G : metricSpace, a : G^ω, p : ⊦ prop_convergent G a} G.universe 
		= [G, a, p] that (G.universe) ([g : G.universe] prop_converges G a g) p 
		# lim 2 %I3 

    	      
theory FunctionLimit : base:?Logic = 
   include ?MetricSpace 
   /T p is the limit of f at "point" a, where A is the larger space and is restricted by cond ❙
   /T *_c-variants: only on pred_as_subs, all the others on ℝ ❙
   prop_isLimit_c : {A : metricSpace,B: metricSpace, cond : A.universe ⟶ prop} ({x : A.universe,p:⊦ cond x}B.universe) ⟶ A.universe ⟶ B.universe ⟶ prop 
   		= [A,B,cond][f][a,l] ∀[ε:ℝ+] ε > 0 ⇒ ∃[δ : ℝ] δ > 0 ∧ ∀[x : A.universe] ∀[p : ⊦ cond x] (d x a) < δ ⇒ (d (f x p) l) < ε 
   prop_hasLimit_c : {A : metricSpace,B: metricSpace, cond : A.universe ⟶ prop} ({x : A.universe,p:⊦ cond x}B.universe) ⟶ A.universe ⟶ prop 
   		= [A,B,cond,f,a] ∃![l : B.universe] prop_isLimit_c A B cond f a l 
   prop_isLimit : {A : metricSpace,B: metricSpace} (A.universe ⟶ B.universe) ⟶ A.universe ⟶ B.universe ⟶ prop 
   		= [A,B,f,a,l] prop_isLimit_c A B ([x]true) ([x,p] f x) a l 
   prop_hasLimit : {A : metricSpace,B: metricSpace} (A.universe ⟶ B.universe) ⟶ A.universe ⟶ prop 
   		= [A,B,f,a] ∃![l : B.universe] prop_isLimit A B f a l
   limit_c : {A : metricSpace, B: metricSpace, cond : A.universe ⟶ prop, f : {x : A.universe,p:⊦ cond x}B.universe, a : A.universe, p : ⊦ prop_hasLimit_c A B cond f a} B.universe 
   		= [A,B,cond,f,a,p] that (B.universe) ([b:B.universe] prop_isLimit_c A B cond f a b) p 
   limit : {A : metricSpace, B: metricSpace, f : A.universe ⟶ B.universe, a : A.universe, p : ⊦ prop_hasLimit A B f a} B.universe 
   		= [A,B,f,a,p] that (B.universe) ([b] prop_isLimit A B f a b) p 


theory Completeness : base:?Logic = 
   include ?MetricSpace 
   include ?SequenceConvergence 
   // d(x_k , x_l ) → 0 for k, l → ∞ ❙
   cauchy : {M: metricSpace} (ℕ ⟶ M.universe) ⟶ prop  
     = [M, seq] ∀[ε : ℝ+] ∀[N : ℕ] ∃[k : ℕ] ∃[l : ℕ] (k ≥ N) ∧ (l > k) ∧ ((d (seq k) (seq l)) < ε) 
     # cauchy 2 
   // every Cauchy sequence in M converges ❙
   complete : {M: metricSpace} prop 
     = [M] ∀[seq] cauchy seq ⇒ prop_convergent M seq  # complete 1 


// MiKo: maybe we should refactor the iterated operation construction into $?monoid$ with the axioms ❚
theory Series : base:?Logic =
  include ?SequenceConvergence 
  include ?MetricMonoid 
  
  partialSum : {G : metricMonoid} G^ω ⟶ ℕ ⟶ (G.universe)  # parSum 2 3 
  axiom_partialSumBase : {G : metricMonoid} ⊦ ∀[S : G^ω] parSum S 0 ≐ (G.unit) 
  axiom_partialSumStep : {G : metricMonoid} ⊦ ∀[S : G^ω] ∀[n] parSum S (succ_nat_lit n) ≐ (G.op) (parSum S n) (S (succ_nat_lit n)) 
  prop_convergent : {G : metricMonoid} G^ω ⟶ prop  = [G][S] prop_convergent G ([n] parSum S n) 
  series : {G : metricMonoid, S: G^ω} dom G  = [G,S] lim (partialSum G S)  # SUM 2  

namespace http://mathhub.info/MitM/core/categories 
import base http://mathhub.info/MitM/Foundation 
// import type http://mathhub.info/MitM/interfaces/TypeConstructors ❚                              

theory Categories : base:?Logic =
    include ☞base:?InformalProofs 

	theory category_theory : base:?Logic =
		universe : 𝒰 10  # U 
		hom : U ⟶ U ⟶ 𝒰 10  # ihom 1 2 
		comp : {a,b,c:U} ihom a b ⟶ ihom b c ⟶ ihom a c  # 5 ∘m 4 
	    identity: {a:U} ihom a a  # iid %I1 
		axiom_assoc : {a,b,c,d:U} ⊦ ∀[f:ihom a b] ∀[g:ihom b c] ∀[h:ihom c d] h ∘m (g ∘m f) ≐ (h ∘m g) ∘m f 
		axiom_id_r : {x:U,a:U} ⊦ ∀[f:ihom a x] f ∘m iid ≐ f 
		axiom_id_l : {x:U,a:U} ⊦ ∀[f:ihom x a] iid ∘m f ≐ f 

		prop_isomorphism = [A,B,f:ihom A B] ∃ [g] g ∘m f ≐ iid ∧ f ∘m g ≐ iid  # prop_isomorphic 3 
		prop_isomorphic = [A,B] ∃[f : ihom A B] prop_isomorphic f  # 1  2 
	
	category = Mod ☞?Categories/category_theory  # Cat 
	objects : Cat ⟶ 𝒰 10  = [𝒞] 𝒞.universe  # | 1 | 
	morphisms : {𝒞: Cat} |𝒞| ⟶ |𝒞| ⟶ 𝒰 10  = [𝒞,a,b] (𝒞.hom) a b  # hom 2 3 
	hom_composition : {𝒞:Cat,a,b,c:|𝒞|} hom a b ⟶ hom b c ⟶ hom a c  = [𝒞,a,b,c,f,g] (𝒞.comp) a b c f g  # 6  5 prec 1 
	id: {𝒞:Cat,a:|𝒞|} hom a a  = [𝒞,a] (𝒞.identity) a # id 2 


theory Opposite : base:?Logic =
    include ?Categories 

    opposite : category ⟶ category  = [𝒞] ['
        universe := (𝒞.universe) ,
        hom := ([a,b] hom b a) ,
        comp := ([a,b,c][f,g] f ∘ g),
        identity := ([a] id a),
        axiom_assoc := ([a,b,c,d] trivial),
        axiom_id_r := ([a,b] trivial),
        axiom_id_l := ([a,b] trivial)
    ']  # 1 op 


theory Product : base:?Logic =
    include ?Categories 
    include ☞base:?ProductTypes 

    product : Cat ⟶ Cat ⟶ Cat  = [𝒞,𝒟] ['
        universe := ((𝒞.universe) × (𝒟.universe)) ,
        hom := ([a,b] (hom (πl a) (πl b)) × (hom (πr a) (πr b))) ,
        comp := ([a,b,c][f,g] ⟨(πl g) ∘ (πl f),(πr g) ∘ (πr f) ⟩ ),
        identity := ([a] ⟨ id (πl a), id (πr a) ⟩),
        axiom_assoc := ([a,b,c,d] trivial),
        axiom_id_r := ([a,b] trivial),
        axiom_id_l := ([a,b] trivial)
    ']  # 1 ×C 2 


theory ArrowCategory : base:?Logic =
    include ?Categories 
    include ☞base:?ProductTypes 
    // include base:?Subtyping ❙

    arr : Cat ⟶ Cat  // = [𝒞] ['
        universe := (Σ A : | 𝒞 |, B : | 𝒞 |. hom A B) ,
        dom : universe ⟶ type := [tr] πl tr ,
        cod : universe ⟶ type := [tr] πl ( πr tr) ,
        arrow : universe ⟶ type := [tr] πr (πr) ,
        hom := ([a,b] Σ p : ((hom (dom a) (dom b)) × (hom (cod a) (cod b))) . ⊦ (πr p) ∘ a ≐ b ∘ (πl p) ) ,
        comp := ([a,b,c][f,g] ⟨⟨(πl (πl g)) ∘ (πl (πl f)),(πr (πl g)) ∘ (πr (πl f)) ⟩,trivial ⟩ ),
        identity := ([a] ⟨⟨ id (dom a), id (cod a) ⟩, trivial⟩),
        axiom_assoc := ([a,b,c,d] trivial),
        axiom_id_r := ([a,b] trivial),
        axiom_id_l := ([a,b] trivial)
    ']  # 1 ×C 2  // Definiens fails ❙




theory SmallCategories : base:?Logic =

    theory small_category_theory : base:?Logic =
    	universe : type  # U 
    	hom : U ⟶ U ⟶ type  # ihom 1 2 
    	comp : {a,b,c:U} ihom a b ⟶ ihom b c ⟶ ihom a c  # 5 ∘m 4 
    	identity: {a:U} ihom a a  # iid %I1 
    	axiom_assoc : {a,b,c,d:U} ⊦ ∀[f:ihom a b] ∀[g:ihom b c] ∀[h:ihom c d] h ∘m (g ∘m f) ≐ (h ∘m g) ∘m f 
    	axiom_id_r : {x:U,a:U} ⊦ ∀[f:ihom a x] f ∘m iid ≐ f 
    	axiom_id_l : {x:U,a:U} ⊦ ∀[f:ihom x a] iid ∘m f ≐ f 
    
	small_category = Mod ☞?SmallCategories/small_category_theory  # SCat 

	include ?Categories 


// theory CategoryOfSmallCategories : base:?Logic =
    include ?Functors ❙
    include ?SmallCategories ❙
    include base:?InformalProofs ❙

    Instance functor_composition (𝒞 : Cat, 𝒟 : Cat, E : Cat, F : functor 𝒞 𝒟, G : functor 𝒟 E) (functor 𝒞 E) ❘ =
        objF = [c : |𝒞|] objF G (objF F c) ❙
        homF : {A,B} hom A B ⟶ hom (objF A) (objF B) ❘ = [A,B][f] homF G (homF F f) ❘ # ihomF 3 ❙
        axiom_id : {A:|𝒞|} ⊦ ihomF (id A) ≐ id (objF A) ❘ = [A] sketch "trivial" ❙
        axiom_comp: {A:|𝒞|,B:|𝒞|,C:|𝒞|}{f : hom A B, g : hom B C} ⊦ ihomF (g ∘ f) ≐ (ihomF g) ∘ (ihomF f) ❘ = [A,B,C][f,g] sketch "trivial" ❙
 //

    Instance small_categories () Cat ❘ =
        universe = SCat ❙
        hom = [𝒞:universe,𝒟:universe] functor 𝒞 𝒟 ❙
        comp = [A:universe,B:universe,C:universe][f : hom A B,g : hom B C] functor_composition A B C f g ❙
 //

namespace http://mathhub.info/MitM/core/categories 
import base http://mathhub.info/MitM/Foundation 

theory Functors : base:?Logic =
	include ?Categories 
	theory functor_theory : base:?Logic > 𝒞 : Cat, 𝒟 : Cat ❘ =
		objF : |𝒞| ⟶ |𝒟| 
		homF : {A,B} hom A B ⟶ hom (objF A) (objF B)  # ihomF 3 
		axiom_id : {A:|𝒞|} ⊦ ihomF (id A) ≐ id (objF A) 
		axiom_comp : {A:|𝒞|,B:|𝒞|,C:|𝒞|}{f : hom A B, g : hom B C} ⊦ ihomF (g ∘ f) ≐ (ihomF g) ∘ (ihomF f) 
	
	functor = [𝒞:Cat,𝒟:Cat] Mod ☞?Functors/functor_theory 𝒞 𝒟 
	objectF : {𝒞,𝒟} functor 𝒞 𝒟 ⟶ |𝒞| ⟶ |𝒟|  = [𝒞,𝒟][F] F.objF  # objF 3 4 
	morphismF : {𝒞,𝒟} {F :functor 𝒞 𝒟} {A:|𝒞|,B:|𝒞|} hom A B ⟶ hom ((F.objF) A) ((F.objF) B) 
	    = [𝒞,𝒟][F][A,B][f] (F.homF) A B f  # homF 3 6 


theory NaturalTransformations : base:?Logic =
    include ?Functors 
    theory naturaltransformation_theory > 𝒞 : Cat, 𝒟 : Cat, F : functor 𝒞 𝒟, G : functor 𝒞 𝒟 ❘ =
        alpha : {C: |𝒞|} hom (objF F C) (objF G C) 
        axiom_alpha_commutes : {c : |𝒞|, cp : |𝒞|} ⊦ ∀[f:hom c cp]
          (homF G f) ∘ (alpha c) ≐ (alpha cp) ∘ (homF F f)  
    
    naturaltransformation = [𝒞 : Cat, 𝒟 : Cat, F : functor 𝒞 𝒟, G : functor 𝒞 𝒟]
        Mod ☞?NaturalTransformations/naturaltransformation_theory 𝒞 𝒟 F G  # natTrans 3 4 

namespace http://mathhub.info/MitM/core/categories 
import base http://mathhub.info/MitM/Foundation 

theory CategoryOfSets : base:?Logic =
    include ?Categories 
    include http://mathhub.info/MitM/Foundation/sets?ZFC 
    include http://mathhub.info/MitM/Foundation/sets?SetTypeConversions 

    composition_of_functions : {s,t,r} (elem s ⟶ elem t) ⟶ (elem t ⟶ elem r) ⟶ (elem s ⟶ elem r) 
        = [s,t,r] [f,g] [x] g (f x)  # 5 ∘c 4 
    cSet : category  = ['
        universe := set ,
        hom := ([s,t] (elem s) ⟶ (elem t)) ,
        comp := composition_of_functions ,
        identity := ([s] [x : elem s] x) ,
        axiom_assoc := ([a,b,c,d] trivial) ,
        axiom_id_r := ([x,u] trivial) ,
        axiom_id_l := ([x,u] trivial)
    '] 


theory Temp : base:?Logic =
    include http://mathhub.info/MitM/Foundation/sets?ZFC 
    include http://mathhub.info/MitM/Foundation/sets?SetTypeConversions 

    Image : {s,t}{f: elem s ⟶ elem t} elem (℘ s) ⟶ elem (℘ t)  # Im 4 3 
    Preimage : {s,t}{f: elem s ⟶ elem t} elem (℘ t) ⟶ elem (℘ s)  # PreIm 4 3 


theory PowersetFunctors : base:?Logic =
    include ?CategoryOfSets 
    include ?Functors 
    include ?Opposite 
    include ?Temp 

    covariantPowersetFunctor : functor cSet cSet  = ['
            objF := ([A] ℘ A),
            homF := ([A,B][f] [x] Im x f),
            axiom_id := ([x] trivial) ,
            axiom_comp := ([a,b,c,f,g] trivial)
        '] 
    contravariantPowersetFunctor : functor (cSet op) cSet  // = ['
            objF := ([A] ℘ A),
            homF := ([A,B][f] [x] PreIm x f),
            axiom_id := ([x] trivial) ,
            axiom_comp := ([a,b,c,f,g] trivial)
        ']  // Definiens takes forever ❙


theory Coalgebras : base:?Logic =
    include ?CategoryOfSets 
    include ?Functors 

    theory coalgebra_theory : base:?Logic =
        T : functor cSet cSet 
        C : set 
        gamma : elem C ⟶ elem (objectF cSet cSet T C) 
    

namespace http://mathhub.info/MitM/core/collections 
import base http://mathhub.info/MitM/Foundation 
import ts http://mathhub.info/MitM/core/typedsets 

theory Properties : base:?Logic =
	include typedsets?SetCollection 
	
	prop_emptyInColl :  {G : type}collection G ⟶ prop  = [G,C] ∅ ∈ C  # prop_emptyInColl 2 
	prop_fullInColl :  {G : type}collection G ⟶ prop  = [G,C] (fullset G) ∈ C  # prop_fullInColl 2 
	prop_unionInColl : {G : type}collection G ⟶ prop  = [G,C] ∀[S] S ⊑ C ⇒ UNION S ∈ C  # prop_unionInColl 2 
	prop_intersectionInColl : {G : type}collection G ⟶ prop  = [G,C] ∀[S] S ⊑ C ∧ INTERSECT S ∈ C  # prop_intersectionInColl  2
	prop_finiteIntersection : {G : type}collection G ⟶ prop  = [G,C] ∀[A]∀[B] A ∈ C ∧ B ∈ C ⇒ (A ∩ B) ∈ C  # prop_finiteIntersection 2
	prop_finiteUnion : {G : type}collection G ⟶ prop  = [G,C] ∀[A]∀[B] A ∈ C ∧ B ∈ C ⇒ (A ∪ B) ∈ C  # prop_finiteUnion 2
	prop_subsetClosed : {G : type}collection G ⟶ prop  = [G,C] ∀[S] ∀[T] S ∈ C ∧ T ⊑ S ⇒ T ∈ C  # prop_subsetClosed 2 
	prop_cover : {G : type}collection G ⟶ set G ⟶ prop  = [G,C,S] S ⊑ UNION C  # 2 covers 3 
	prop_subcover : {G : type}collection G ⟶ collection G ⟶ set G ⟶ prop  = [G,C,D,S] C ⊑ D ∧ C covers S  # 2 subcover 3 on 4 
	prop_pairwiseDisjoint : {G : type}collection G ⟶ prop  = [G,C] ∀[S] ∀[T] S ∈ C ∧ T ∈ C ⇒ disjoint S T  # pairwiseDisjoint 2 
	prop_closedUnderComplements : {G : type}collection G ⟶ prop  = [G,C] ∀[S] (S ∈ C) ⇒ (compl S) ∈ C  # prop_closedUnderComplements 2 


theory Partition : base:?Logic = 
  include ?Properties 
  include ☞base:?InformalProofs 

  prop_isPartition : {G : type} collection G ⟶ prop 
    = [G,C] C covers (fullset G) ∧ ¬ (prop_emptyInColl C) ∧ pairwiseDisjoint C 
	  # isPartition 2 
	  
	theory partition_theory : base:?Logic > X : type ❘ =
		include typedsets?SetCollection/setColl_theory (X) 
		axiom_covers : ⊦ coll covers (fullset X) 
		axiom_nonEmpty : ⊦ ¬ (∅ ∈ coll) 
		axiom_pairwisedisjoint : ⊦ pairwiseDisjoint coll 
	
	partition = [X : type] Mod ☞?Partition/partition_theory (X) 


// theory TaggedPartition : base:?Logic =
	include ?Partition ❙
	include ts:?TaggedCollectoin ❙
	

namespace http://mathhub.info/MitM/core/collections 
import base http://mathhub.info/MitM/Foundation 

theory Matroids : base:?Logic =
	include ?Properties 
	include typedsets?FiniteCardinality 
	include arithmetics?NaturalArithmetics 

	theory matroid_theory : base:?Logic > X : type ❘ =
		include typedsets?SetCollection/setColl_theory (X) 
		
		axiom_finite : {s : set X} ⊦ s ∈ coll ⟶ ⊦ s finite 
		axiom_empty : ⊦ prop_emptyInColl coll 
		axiom_subset : ⊦ prop_subsetClosed coll 
		axiom_augmentation : ⊦ ∀ [A] ∀ [B] A ∈ coll ∧ B ∈ coll ∧ | B | ≤ | A | 
				⇒ ∃ [x] x ∈ (A \ B) ∧ (B ∪ (single x)) ∈ coll 
	

namespace http://mathhub.info/MitM/core/elliptic_curves 
import base http://mathhub.info/MitM/Foundation 

theory Weierstrass_model : ?Base = 
	include ☞http://mathhub.info/MitM/core/typedsets?Injective 
	include ☞base:?Vectors 

 weierstrass_model : type 
 polynomial_equation : weierstrass_model ⟶ (polynomial rationalField) 
 polynomial_equation_injectivity : {A, B} ⊦ polynomial_equation A ≐ polynomial_equation B ⟶ ⊦ A ≐ B 
    // As the Weierstrass model is really defined by the polynomial_equation, this is really what defines equality. (1) ❙

 discriminant : weierstrass_model ⟶ ℤ
    // missing that this discriminant is really the discriminant of the polynomial equation
    // and thus that this factors through the discriminant defined (elsewhere) for multivariate polynomials ❙
    
    // Dennis: is it okay to just define the discriminant of a weierstrass model as above (i.e. as the discriminant of the associated polynomial?) ❙ 

 a_invariants : weierstrass_model ⟶ (vector ℤ 5) 
 a_invariants_factors_injectivity : ⊦ is_injective a_invariants 
    // if formulation of (1) changes, this should change too
    // really, this should go through the polynomial_equation, as it is more core to defn of a_invariants ❙

namespace http://mathhub.info/MitM/core/elliptic_curves 
import fnd http://mathhub.info/MitM/Foundation 

theory a_Invariants : ?Base =
  include ?Minimal_Weierstrass_model 
  a_invariants : elliptic_curve ⟶ (vector ℤ 5)  = [A] a_invariants (minimal_Weierstrass_model A) 

   
namespace http://mathhub.info/MitM/core/elliptic_curves 

import base http://mathhub.info/MitM/Foundation 
import num http://mathhub.info/MitM/core/arithmetics 

theory Base : base:?Logic =
	include ☞num:?IntegerArithmetics 
	include algebra?Field 
	include ☞base:?Matrices 
	include algebra?RationalPolynomials 
	power_series : type                                       

namespace http://mathhub.info/MitM/core/elliptic_curves 

theory Complex_multiplication : ?Base =
  include ?Elliptic_curve 
  complex_multiplication : elliptic_curve ⟶ prop 

 
namespace http://mathhub.info/MitM/core/elliptic_curves 

theory Conductor : ?Base =
  include ?Elliptic_curve 
  conductor : elliptic_curve ⟶ ℤ 

namespace http://mathhub.info/MitM/core/elliptic_curves 

theory Discriminant : ?Base = 
  include ?Minimal_Weierstrass_model 
  // include ?Weierstrass_model ❙
  discriminant : elliptic_curve ⟶ ℤ  = [A] discriminant (minimal_Weierstrass_model A) 

namespace http://mathhub.info/MitM/core/elliptic_curves 
import lmfdb http://www.lmfdb.org/omf 

theory Elliptic_curve_toolchest : ?Base = 
    include ?Modular_degree 
    include ?a_Invariants 
    include ?Discriminant 
    // include ec_2_adic_data ❙
    // include ec_padic_data ❙

    // include lmfdb:?LMFDB_label ❙
    // include lmfdb:?Cremona_label ❙          
    // clash in some names, such as conductor_component, although domains are different
    // Dennis: Should be fine; Florian massively improved disambiguation at some point :) ❙

    include ?Isogeny_class 
    include ?q_Expansion 
    include ?Complex_multiplication 
    include ?Conductor 
    
    // include minimal_Weierstrass_model ❙ 
    // discriminant makes this redundant
    // Dennis: true; commented it out  ❙

namespace http://mathhub.info/MitM/core/elliptic_curves 

theory Elliptic_curve : ?Base = 
  include ?Weierstrass_model 
    
  elliptic_curve : type 
  
  base_field : elliptic_curve ⟶ field 

  weierstrass_model_construction : weierstrass_model ⟶ elliptic_curve 

  minimal_Weierstrass_model : elliptic_curve ⟶ weierstrass_model 
  
  construction_surjective: {A} ⊦ weierstrass_model_construction (minimal_Weierstrass_model A) ≐ A 
  

                                          
namespace http://mathhub.info/MitM/core/elliptic_curves 

theory Isogeny_class : ?Base =
  include ?Conductor 
    
  isogeny_class: type 
  isogeny_equivalence_class: elliptic_curve ⟶ isogeny_class 
    
  isogenies_preserve_conductor: {A : elliptic_curve, B:elliptic_curve} ⊦ isogeny_equivalence_class A ≐ isogeny_equivalence_class B ⟶ ⊦ conductor A ≐ conductor B 
    // should really be defined as a quotient ❙

    
namespace http://mathhub.info/MitM/core/elliptic_curves 

theory Minimal_Weierstrass_model : ?Base =
  include ?Elliptic_curve 

 minimal : weierstrass_model ⟶ weierstrass_model 
 is_minimal : weierstrass_model ⟶ prop  = [A] (minimal A) ≐ A            
    // need separators ❙
    
 // minimality_condition : {A : tm Weierstrass_model,B : tm Weierstrass_model} ⊦ (minimal A) ≐ B → ⊦ absolute_value (discriminant B) ≤ absolute_value (discriminant A) ❙
 // Dennis: For some reason this doesn't typecheck. I have an idea why, but no idea how to solve it yet. ❙
 minimality_idempotence : {A} ⊦ minimal (minimal A) ≐ minimal A 
    
    // the whole thing with minimal stinks of redundancy. it should be reusing partial orders and minimality over N ❙

  minimality_of_minimal_Weierstrass_model : {A} ⊦ is_minimal (minimal_Weierstrass_model A) 
  injective_minimal_Weierstrass_model : {A,B} ⊦ minimal_Weierstrass_model A ≐ minimal_Weierstrass_model B ⟶ ⊦ A ≐ B 

  // roundtrip_Weierstrass_model_construction : {A} ⊦ A ≐ Weierstrass_model_construction (minimal_Weierstrass_model A) ❙
  // Dennis: now subsumed by elliptic_curve?construction_surjective ❙

namespace http://mathhub.info/MitM/core/elliptic_curves 

theory Modular_degree : ?Base =
  include ?Conductor 
  modular_degree : elliptic_curve ⟶ ℤ 

namespace http://mathhub.info/MitM/core/elliptic_curves 

theory q_Expansion : ?Base =             // illustrates gain in introducing isogeny_class, could talk about modular forms as well ❙
  include ?Isogeny_class 
  
  q_expansion: elliptic_curve ⟶ power_series 
  q_expansion_factors_through_isogeny_class: {A, B} ⊦ isogeny_equivalence_class A ≐ isogeny_equivalence_class B ⟶ ⊦ q_expansion A ≐ q_expansion B 

 
namespace http://mathhub.info/MitM/core/functional-analysis 

import base http://mathhub.info/MitM/Foundation 
import calculus http://mathhub.info/MitM/core/calculus 
import algebra http://mathhub.info/MitM/core/algebra 
import topo http://mathhub.info/MitM/core/topology 
import arith http://mathhub.info/MitM/core/arithmetics 

theory NormedSpace : base:?Logic =
	include ☞algebra:?Vectorspace 
	include ☞algebra:?RealField 
	
	theory normedspace_theory : base:?Logic =
		include ☞algebra:?Vectorspace/vectorspace_theory (realField) 
		norm : universe ⟶  ℝ^+  # || 1 || 
		
		axiom_multiplicativity : ⊦ ∀[x : universe] ∀[a : ℝ] ☞arith:?RealArithmetics?multiplication (☞arith?RealArithmetics?absolute a) || x || ≐ || (scalarmult) a x ||
		axiom_subadditivity : ⊦ ∀[x : universe] ∀[y : universe] (|| op x y ||) ≤ (||x|| + ||y||) // ⊦ ||(x + y)|| ≤ (||x|| + ||y||) 
		axiom_positivity : ⊦ ∀[x : universe] 0 ≤ || x || 
		axiom_definiteness : ⊦ ∀[x : universe] 0.0 ≐ || x || ⇔ x ≐ unit  // ⊦ ||x||≐0 ⇔ x ≐ e  ❙
	 
	normedSpace : kind  = Mod ☞?NormedSpace/normedspace_theory 
	
	include ☞calculus:?MetricSpace 
	
	implicit view NormedSpaceAsMetricSpace : calculus:?MetricSpace/metricSpace_theory -> ?NormedSpace/normedspace_theory =
		universe = universe  
		d = [x : universe, y : universe] || x - y ||
		axiom_triangleInequality = sketch "follows from axiom_subadditivity" 
		axiom_isPseudoMetric = sketch "follows from axiom_positivity, and from the symmetry in the metric as implied by multiplicativity" 
	

	

theory BanachSpace : base:?Logic =
  include ?NormedSpace 
	include ☞calculus:?Completeness 
	
	theory normedmetric_theory =
		include ?NormedSpace/normedspace_theory 
		structure ms : calculus:?MetricSpace/metricSpace_theory abbrev ?NormedSpace/NormedSpaceAsMetricSpace 
	
	normedmetric = Mod ☞?BanachSpace/normedmetric_theory 

	banach : {n : normedSpace} prop  = [n] complete n  // TODO also as models-of ❙


theory BanachAlgebra : base:?Logic =
  include ?BanachSpace 
  
  


// theory NormedRealVectorSpaces : base:?Logic =
	include algebra:?RealVectorspace ❙
	include arith:?RealArithmetics ❙
	// TODO generalize ❙
	// include ?NormedSpace ❙
	
	Norm: ℝ1.universe ⟶ ℝ^+ ❘ = [x] |x| ❘ # || 1 || ❙
	Axiom_Multiplicativity : ⊦ ∀[x : ℝ1.universe] ∀[α : ℝ] || (ℝ1.scalarmult) α x || ≐ | α | ⋅ || x || ❙ // error: type of bound variable too big: kind ❙
	Axiom_Subadditivity : ⊦ ∀[x] ∀[y] (|| (ℝ1.op) x y ||) ≤ (||x|| + ||y||) ❙
	Axiom_Positivity : ⊦ ∀[x] 0 ≤ || x || ❙
	Axiom_Definiteness : ⊦ ∀[x] ||x||≐0 ⇔ x ≐ (ℝ1.unit)  ❙

namespace http://mathhub.info/MitM/core/geometry 

import base http://mathhub.info/MitM/Foundation 
import arith http://mathhub.info/MitM/core/arithmetics 
// TODO: ❚
import rules scala://rules.frameit.mmt.kwarc.info 

fixmeta base:?Logic 

theory 3DGeometry =
  include ☞base:?ProductTypes 
  include ?Geometry 

    // ℝ³ ❙

  point = ℝ × ℝ × ℝ 
  xofpoint : point ⟶ ℝ  = [p] πl p  # 1 _x prec 50 
  yofpoint : point ⟶ ℝ  = [p] πl (πr p)  # 1 _y prec 50 
  zofpoint : point ⟶ ℝ  = [p] πr (πr p)  # 1 _z prec 50 

  point_addI = [p1,p2] ⟨ (p1 _x + p2 _x), (p1 _y + p2 _y), (p1 _z + p2 _z) ⟩ 
  point_subtractI = [p1,p2] ⟨ (p1 _x - p2 _x), (p1 _y - p2 _y), (p1 _z - p2 _z) ⟩ 
  vec_multI = [r,p] ⟨ r ⋅ p _x, r ⋅ p _y, r ⋅ p _z ⟩ 
  scalar_productI = [p1,p2] (p1 _x ⋅ p2 _x) + (p1 _y ⋅ p2 _y) + (p1 _z ⋅ p2 _z) 

  include (?Geometry/Common point point_addI point_subtractI vec_multI scalar_productI) 


  vec_cross : point ⟶ point ⟶ point  = [v, w ] ⟨ ( v _y  ⋅ w _z  - v _z ⋅ w _y ) , ( v _z  ⋅ w _x  - v _x ⋅ w _z ) , ( v _x  ⋅ w _y  - v _y ⋅ w _x ) ⟩  # 1 Vcross  2  



theory InterceptTheorem =
    include ☞?3DGeometry 
    // naming like the images on
    https://en.wikipedia.org/wiki/Intercept_theorem ❙

    S : point 
    A : point 
    B : point 
    C : point 
    D : point 

    line1 : ⊦ S on (from A to B) 
    line2 : ⊦ S on (from C  to D) 
    twolines: ⊦  ¬ (A -- B) ∥ (C -- D) 
    par : ⊦ (A -- C) ∥ (B -- D) 

    ratio1: ⊦ (d- S A ) / (d- A B) ≐ (d- S C) / (d- C D) 
    ratio2: ⊦ (d- S A ) / (d- S B) ≐ (d- S C) / (d- S D) 
    ratio3: ⊦ (d- S A ) / (d- S B) ≐ (d- A C) / (d- B D) 
    ratio4: ⊦ (d- S C ) / (d- S D) ≐ (d- A C) / (d- B D) 


theory 3DTriangles =
    include ☞?3DGeometry 

    include (?Geometry/Triangles point point_addI point_subtractI vec_multI scalar_productI) 

    area: triangle ⟶ ℝ  = [T]  ( | ( _A T  --  _B T ) Vcross ( _A T -- _C T ) | )  ⋅ ( 1 / 2 ) #  1 
    // area definition that does not use height; can be computed without needing ι ❙


theory Planes =
    include ☞?3DTriangles 

    plane : type 
    triangleToPlane: triangle ⟶ plane  # PofΔ 1 
    ParametrizedPlane: point ⟶ point ⟶ point ⟶ plane  # Ppara 1 2 3 
    pointNormalPlane: point ⟶ point ⟶ plane  # Ppn 1 2 

    planeNormal : plane ⟶ point  # Pnormal 1 prec 50
    planeBase : plane ⟶ point  # Pbase 1  prec 50

    PlaneBaseAxiom1 : {v, w, b } ⊦ Pbase (Ppara b v w ) ≐ b  role ForwardRule

    normalAxiom1 : { v, w, b } ⊦ ( Pnormal ( Ppara b v w ) ) ≐ ( normalize ( v Vcross w ) )  role ForwardRule 
    normalAxiom2 : { v, b } ⊦ ( Pnormal ( Ppn b v ) ) ≐ ( norm ( v ) )  role ForwardRule
    triangleAxiom :  { T } ⊦ ( PofΔ T ) ≐ Ppara ( _A T ) ( _A  T -- _B T  ) ( _A  T -- _B T)   role ForwardRule 

    pointOnPlane : point ⟶ plane ⟶ bool = [v , p] < Pnormal p , v -- Pbase p > ≐  0   #  1 VonP 2 
    lineOnPlane : line ⟶ plane ⟶ bool = [l,p ] ( ( from l ) VonP p ) ∧  ( ( from l ) ++( dir l ) ) VonP p #  1 LonP 2 

    LinePlaneCollisionPoint : { A, B } ( ⊦ dir A ⊥⊥ Pnormal B ) ⟶ point   # colPLV 1 2 3 
    LinePlaneCollisionPointAxiom : {A , B, p1 } ⊦  ( colPLV  A B p1 ) VonP B   ∧  ( colPLV  A B p1 ) on A 

    parallelPlanes : plane ⟶ plane ⟶ bool = [ p1 ,p2] ( Pnormal p1 ) ∥ ( Pnormal p2 ) # 1 Ppar 2 prec 50 
    samePlane: plane ⟶ plane ⟶ bool  = [ p1 , p2] ( Pbase p1 VonP  p2 ) ∧ ( p1 Ppar p2 )# Psame 1 2
    collidePlane : plane ⟶ plane ⟶ bool  = [ A ,B ] ( ¬ A Ppar  B ) ∨ Psame A B  #  colP 1 2 

    collisionLine: {A, B } ⊦ colP A B ⟶ ⊦ ¬ Psame A B ⟶ line  # colPPL 1 2 3 4
    collisionLineAxiom: {A, B, p1 ,p2} ⊦ ( ( colPPL A B p1 p2 ) LonP A ) ∧( ( colPPL A B p1 p2 ) LonP B )


// TODO Generalize to n-Spheres? ❚
// theory Sphere : http://mathhub.info/MitM/Foundation?Math =
    include ?Vector ❙
    include ?Lines ❙

    sphere: type ❘ # S ❙
    sphereAround: V ⟶ ℝ ⟶ S ❘# So 1 2 ❙
    center: S ⟶ V ❘ # Sm 1 ❙
    centerAxiom: {m,r}  ⊦ Sm ( So m r) ≐ m ❙
    radius: S ⟶ ℝ ❘ # Sr 1 ❙
    radiusAxiom : {m,r} ⊦ Sr (So m r) ≐ r ❙

    onSphere: S ⟶ V ⟶ bool ❘ =  [s, v] ( d ( Sm s ) ( v ) ) ≐ ( Sr s ) ❘ # 2 VonS  1 ❙
    inSphere: S ⟶ V ⟶ bool ❘ =  [s, v] ( d ( Sm s ) ( v ) ) < ( Sr s ) ❘ # 2 VinS  1 ❙

    collidesSphereLine: S ⟶ L ⟶ bool ❘ = [s,l] ∃ [v] ( v VonL  l ) ∨  (v VinS s ) ❘ # 1 ScolL  2 ❙

    circumfenceSphere: S ⟶ ℝ ❘ = [s] ( Sr s ) ⋅ ( Sr s) ⋅ 4 ⋅ π  ❘ # CS 1 ❙
    areaSphere :  S ⟶ ℝ ❘ = [s] ( Sr s ) ⋅ ( Sr s ) ⋅ (Sr s) ⋅ ( 4 / 3 ) ⋅ π  ❘ # AS 1 ❙


// theory Pyramid :  http://mathhub.info/MitM/Foundation?Math =
    include ☞http://BenniDoes.Stuff/?Vector ❙
    include ☞http://BenniDoes.Stuff/?Triangle ❙

    Pyramid : type ❘ # Pyr ❙
    pyramidOf : V ⟶ V ⟶ V ⟶ V ⟶ Pyr ❘ # Pyrof 1 2 3 4 ❙
    P_A : Pyr ⟶ V ❘ # P_A 1❙
    P_A_axiom : {a :V, b :V, c :V, dd :V } ⊦ ( P_A ( Pyrof a b c dd) ) ≐  a  ❘ role ForwardRule❙
    P_B : Pyr ⟶ V ❘ # P_B 1❙
    P_B_axiom : {a :V, b :V, c :V, dd :V } ⊦ ( P_B ( Pyrof a b c dd) ) ≐  b  ❘ role ForwardRule❙
    P_C : Pyr ⟶ V ❘ # P_C 1❙
    P_C_axiom : {a :V, b :V, c :V, dd :V } ⊦ ( P_C ( Pyrof a b c dd) ) ≐  c  ❘ role ForwardRule❙
    P_D : Pyr ⟶ V ❘ # P_D 1❙
    P_D_axiom : {a :V, b :V, c :V, dd :V } ⊦ ( P_D ( Pyrof a b c dd) ) ≐  dd  ❘ role ForwardRule❙

    Volume_Pyramid: Pyr ⟶ ℝ ❘ = [p ] ( 1 / 6) ⋅ ( < ( ( ( P_B p ) ⁻ ( P_A p ) ) Vcross ( ( P_C  p ) ⁻ ( P_A p ) ) ), (( P_D  p ) ⁻ ( P_A p )  ) > ) ❘# VolofP 1 ❙

namespace http://mathhub.info/MitM/core/geometry 

import base http://mathhub.info/MitM/Foundation 
import arith http://mathhub.info/MitM/core/arithmetics 
// TODO: ❚
import rules scala://rules.core.mitm.mmt.kwarc.info 

fixmeta base:?Logic 

theory Geometry =
  include ☞arith:?RealArithmetics 
  include ☞base:?Trigonometry 

  theory Common > point : type,
        add : point ⟶ point ⟶ point,
        subtract : point ⟶ point ⟶ point,
        mult : ℝ ⟶ point ⟶ point,
        scp : point ⟶ point ⟶ ℝ ❘ =

  // ℝ^n ❙

      point_add : point ⟶ point ⟶ point  = add  # 1 ++ 2 prec 12 
      point_subtract : point ⟶ point ⟶ point  = subtract  # 1 -- 2 prec 12 
      vec_mult : ℝ ⟶ point ⟶ point  = mult  # 1 ⋅⋅ 2 prec 22 
      scalar_product : point ⟶ point ⟶ ℝ  = scp  # < 1 , 2 > 
      norm : point ⟶ ℝ  = [p] √ <p,p>  # | 1 | 
      metric : point ⟶ point ⟶ ℝ  = [p1,p2] | (p1 -- p2) |  # d- 1 2 
      rule rules?MetricCommutative 

      normalize: point ⟶ point  = [v] (1 / ( | v | )) ⋅⋅ v  # norm 1 


      // Angles ❙

      angle: point ⟶ point ⟶ ℝ  = [v,w] acos ( < v,w > / (|v| ⋅ |w|))  #  1 2 prec 1 
      angle_between: point ⟶ point ⟶ point ⟶ ℝ  = [x,y,z] ∠ (x -- y) (z -- y)  #  1 , 2 , 3 
      rule rules?AngleInvertible 

      parallel: point ⟶ point ⟶ bool  = [v,w] (∠ v w ≐ 0) ∨ (∠ v w ≐ pi_num)  # 1  2 
      orthogonal: point ⟶ point ⟶ bool  = [v,w] < v ,w > ≐ 0  # 1 ⊥⊥ 2    //  jbot ❙
      rightangle: ℝ ⟶ bool  = [x] x ≐ pi_num / 2   #  1 //  jcheck ❙

      // Lines ❙

      line_type : type  # line 
      lineOf : point ⟶ point ⟶ line  # from 1 to 2 
      basepoint : line ⟶ point  # from 1 prec 1 
      targetpoint : line ⟶ point  # to 1 prec 1 
      axiom_basepoint : {p1,p2} ⊦ from (from p1 to p2) ≐ p1   role ForwardRule 
      axiom_targetpoint : {p1,p2} ⊦ to (from p1 to p2) ≐ p2   role ForwardRule 

      lineDirection: line ⟶ point  =  [l] norm (( to l ) -- ( from l ))  # dir 1  // wut? ❙

      onLine : line ⟶ point ⟶ bool  # 2 on 1   // definiens? ❙
      sameLine: line ⟶ line ⟶ bool  = [A ,B] ( (from B ) on A ) ∧ ( (lineDirection B) ∥ (lineDirection A) )  # 1  2

      intersect : line ⟶ line ⟶ bool  = [A,B] ∃ [p] (p on A) ∧ (p on B) ∧ (¬ A ≅ B)  # colL 1 2 
      pointOfIntersection : {A ,B } ( ⊦ colL A B ) ⟶ point  # colLV 1 2 3  
      parallelLine: line ⟶ line ⟶ bool  = [A,B] lineDirection A ∥ lineDirection B  # paraL 1 2 
      pointOfIntersectionAxiom: {A, B, p} ⊦ ( ( colLV A B  p) on A ) ∧ ( ( colLV A B  p) on B) 

  

  theory Triangles > point : type,
          addI : point ⟶ point ⟶ point,
          subtractI : point ⟶ point ⟶ point,
          multI : ℝ ⟶ point ⟶ point,
          scpI : point ⟶ point ⟶ ℝ ❘ =

    include (?Geometry/Common point addI subtractI multI scpI) 

    triangle : type 
    triangle_constructor : point ⟶ point ⟶ point ⟶ triangle  # Δ 1 2 3 

    triangle_point1 : triangle ⟶ point  # _A 1 prec 50 
    triangle_point2 : triangle ⟶ point  # _B 1 prec 50 
    triangle_point3 : triangle ⟶ point  # _C 1 prec 50 

    alpha_angle : triangle ⟶ ℝ  #  1 prec 50  = [T] angle ( _B T -- _A T ) ( _C T -- _A T )
    beta_angle  : triangle ⟶ ℝ  #  1 prec 50  = [T] angle ( _A T --  _B T ) ( _C T -- _B T )
    gamma_angle : triangle ⟶ ℝ  #  1 prec 50  = [T] angle ( _A T -- _C T  ) ( _B T -- _C T )

    a_triangle: triangle ⟶ ℝ  = [T] d- ( _B T) ( _C T)  # _a 1 prec 50 
    b_triangle: triangle ⟶ ℝ  = [T] d- ( _A T) ( _C T)  # _b 1 prec 50 
    c_triangle: triangle ⟶ ℝ  = [T] d- ( _A T) ( _B T)  # _c 1 prec 50 


    height_triangle_basepoint_a: triangle ⟶ point  # _haV 1 prec 50 
    height_triangle_basepoint_a_online_axiom: { T } ⊦ ( _haV T ) on ( from ( _B T) to ( _C T ) ) 
    height_triangle_basepoint_a_orthogonal_axiom: { T } ⊦ ( _haV T -- _B T ) ⊥⊥ ( _haV T -- _A T ) 
    ha_triangle_length: triangle ⟶ ℝ  = [T] d- ( _A T ) ( _haV T  ) # _ha 1 prec 50 

    height_triangle_basepoint_b: triangle ⟶ point  # _hbV 1 prec 50 
    height_triangle_basepoint_b_online_axiom: { T } ⊦ ( _hbV T ) on ( from ( _A T) to ( _C T ) ) 
    height_triangle_basepoint_b_orthogonal_axiom: { T } ⊦ ( _hbV T -- _A T ) ⊥⊥ ( _hbV T -- _B T ) 
    hb_triangle_length: triangle ⟶ ℝ  = [T] d- ( _B T ) ( _hbV T  ) # _hb 1 prec 50 

    height_triangle_basepoint_c: triangle ⟶ point  # _hcV 1 prec 50 
    height_triangle_basepoint_c_online_axiom: { T } ⊦ ( _hcV T ) on ( from ( _B T) to ( _A T ) ) 
    height_triangle_basepoint_c_orthogonal_axiom: { T } ⊦ ( _hcV T -- _B T ) ⊥⊥ ( _hcV T -- _C T ) 
    hc_triangle_length: triangle ⟶ ℝ  = [T] d- ( _C T ) ( _hcV T  ) # _hc 1 prec 50 

    lawOfCosine_Alpha: { T } ⊦ ( _a T ⋅ _a T ) ≐ ( _b T ⋅ _b T ) + ( _c T ⋅ _c T ) + 2 ⋅ _b T ⋅ _c T ⋅  ( cos ( _α T ) )
    lawOfCosine_Beta : { T } ⊦ ( _b T ⋅ _b T ) ≐ ( _a T ⋅ _a T ) + ( _c T ⋅ _c T ) + 2 ⋅ _a T ⋅ _c T ⋅  ( cos ( _β T ) )
    lawOfCosine_Gamma: { T } ⊦ ( _c T ⋅ _c T ) ≐ ( _a T ⋅ _a T ) + ( _b T ⋅ _b T ) + 2 ⋅ _a T ⋅ _b T ⋅  ( cos ( _γ T ) )

    lawOfSinesAB: { T } ⊦ _a  T / sin ( _α T ) ≐ _b T / sin ( _β T ) 
    lawOfSinesAC: { T } ⊦ _a  T / sin ( _α T ) ≐ _c T / sin ( _γ T ) 
    lawOfSinesCB: { T } ⊦ _c  T / sin ( _γ T ) ≐ _b T / sin ( _β T ) 

    angleSum = {T} ⊦ (( _α T) + ( _β T) + ( _γ T) )≐ pi_num 
    area: triangle ⟶ ℝ  = [T] ( _hb T) ⋅ ( _b T) / 2  #  1 prec 1 
  

  theory SymmetricTriangles > point : type,
         addI : point ⟶ point ⟶ point,
         subtractI : point ⟶ point ⟶ point,
         multI : ℝ ⟶ point ⟶ point,
         scpI : point ⟶ point ⟶ ℝ ❘ =
    include (?Geometry/Triangles point addI subtractI multI scpI) 

    symmetric_α: triangle ⟶ bool  = [T] _β T ≐ _γ T  # sym_α 1 
    symmetric_β: triangle ⟶ bool  = [T] _α T ≐ _γ T  # sym_β 1 
    symmetric_γ: triangle ⟶ bool  = [T] _α T ≐ _β T  # sym_γ 1 

    symmetric_edges_α: {T} {p : ⊦ (sym_α T) } ⊦ _b T ≐ _c T 
    symmetric_edges_β: {T} {p : ⊦ (sym_β T) } ⊦ _a T ≐ _c T 
    symmetric_edges_γ: {T} {p : ⊦ (sym_γ T) } ⊦ _a T ≐ _b T 

    symmetric_α_edges: {T} {p : ⊦ ( _b T ≐ _c T)} ⊦ sym_α T 
    symmetric_β_edges: {T} {p : ⊦ ( _a T ≐ _c T)} ⊦ sym_β T 
    symmetric_γ_edges: {T} {p : ⊦ ( _a T ≐ _b T)} ⊦ sym_γ T 
  

  theory RightTriangles > point : type,
            addI : point ⟶ point ⟶ point,
            subtractI : point ⟶ point ⟶ point,
            multI : ℝ ⟶ point ⟶ point,
            scpI : point ⟶ point ⟶ ℝ ❘ =
    include (?Geometry/Triangles point addI subtractI multI scpI) 

    pythagoras_alpha = [T]  ( _c T) ⋅ ( _c T) + ( _b T) ⋅ ( _b T) ≐ ( _a T) ⋅ ( _a T) 
    pythagoras_beta = [T]  ( _a T) ⋅ ( _a T) + ( _c T) ⋅ ( _c T) ≐ ( _b T) ⋅ ( _b T) 
    pythagoras_gamma = [T]  ( _a T) ⋅ ( _a T) + ( _b T) ⋅ ( _b T) ≐ ( _c T) ⋅ ( _c T) 

    right_alpha_prop = [T] ✓  _α T 
    right_beta_prop = [T] ✓  _β T 
    right_gamma_prop = [T] ✓  _γ T 

    pythagoras_theorem_alpha : {T}  { p :  ⊦ right_alpha_prop T } ⊦ pythagoras_alpha  T 
    pythagoras_theorem_beta : {T}  { p :  ⊦ right_beta_prop T } ⊦ pythagoras_beta  T 
    pythagoras_theorem_gamma : {T}  { p :  ⊦ right_gamma_prop T } ⊦ pythagoras_gamma  T 

    geometric_mean_alpha = [T]  ( _ha T ⋅ _ha T ) ≐ ( d- ( _haV T ) ( _B T ) ) ⋅ ( d- ( _haV T) ( _C T ) ) 
    geometric_mean_beta = [T]  ( _hb T ⋅ _hb T ) ≐ ( d- ( _hbV T ) ( _A T ) ) ⋅ ( d- ( _hbV T) ( _C T ) ) 
    geometric_mean_gamma = [T]  ( _hc T ⋅ _hc T ) ≐ ( d- ( _hcV T ) ( _B T ) ) ⋅ ( d- ( _hcV T) ( _A T ) ) 

    geometric_mean_theorem_alpha : {T} { p :  ⊦ ( ✓  _α T  ) } ⊦ geometric_mean_alpha T 
    geometric_mean_theorem_beta : {T} { p :  ⊦ ( ✓  _β T  ) } ⊦ geometric_mean_beta T 
    geometric_mean_theorem_gamma : {T} { p :  ⊦ ( ✓  _γ T  ) } ⊦ geometric_mean_gamma T 

    cathetus_alpha_1 = [T]  ( _b T ⋅ _b T  ) ≐ _a T ⋅ ( d- ( _haV T) ( _C T ) )
    cathetus_alpha_2 = [T]  ( _c T ⋅ _c T  ) ≐ _a T ⋅ ( d- ( _haV T) ( _B T ) )

    cathetus_beta_1 = [T]  ( _c T ⋅ _c T  ) ≐ _b T ⋅ ( d- ( _hbV T) ( _A T ) )
    cathetus_beta_2 = [T]  ( _a T ⋅ _a T  ) ≐ _b T ⋅ ( d- ( _hbV T) ( _C T ) )

    cathetus_gamma_1 = [T]  ( _a T ⋅ _a T  ) ≐ _c T ⋅ ( d- ( _hcV T) ( _B T ) )
    cathetus_gamma_2 = [T]  ( _b T ⋅ _b T  ) ≐ _c T ⋅ ( d- ( _hcV T) ( _A T ) )

    catheus_theorem_alpha_1 : {T} { p :  ⊦ ( ✓  _α T  ) } ⊦ cathetus_alpha_1 T 
    catheus_theorem_alpha_2 : {T} { p :  ⊦ ( ✓  _α T  ) } ⊦ cathetus_alpha_2 T 

    catheus_theorem_beta_1 : {T} { p :  ⊦ ( ✓  _β T  ) } ⊦ cathetus_beta_1 T 
    catheus_theorem_beta_2 : {T} { p :  ⊦ ( ✓  _β T  ) } ⊦ cathetus_beta_2 T 

    catheus_theorem_gamma_1 : {T} { p :  ⊦ ( ✓  _γ T  ) } ⊦ cathetus_gamma_1 T 
    catheus_theorem_gamma_2 : {T} { p :  ⊦ ( ✓  _γ T  ) } ⊦ cathetus_gamma_2 T 
  

namespace http://mathhub.info/MitM/core/geometry 

import base http://mathhub.info/MitM/Foundation 
import arith http://mathhub.info/MitM/core/arithmetics 
// TODO: ❚
import rules scala://rules.frameit.mmt.kwarc.info 

fixmeta base:?Logic 

theory PlanarGeometry =
  include ☞base:?ProductTypes 
  include ?Geometry 

  // ℝ² ❙

  point = ℝ × ℝ 
  xofpoint : point ⟶ ℝ  = [p] πl p  # 1 _x prec 50 
  yofpoint : point ⟶ ℝ  = [p] πr p  # 1 _y prec 50 

  point_addI = [p1,p2] ⟨ (p1 _x + p2 _x), (p1 _y + p2 _y) ⟩ 
  point_subtractI = [p1,p2] ⟨ (p1 _x - p2 _x), (p1 _y - p2 _y) ⟩ 
  vec_multI = [r,p] ⟨ r ⋅ p _x, r ⋅ p _y ⟩ 
  scalar_productI = [p1,p2] (p1 _x ⋅ p2 _x) + (p1 _y ⋅ p2 _y) 

  include (?Geometry/Common point point_addI point_subtractI vec_multI scalar_productI) 

namespace http://mathhub.info/MitM/core/graphs
import base http://mathhub.info/MitM/Foundation 
import ts http://mathhub.info/MitM/core/typedsets 
import num http://mathhub.info/MitM/core/arithmetics 

theory Graphs : base:?Logic =
    include ☞ts:?AllSets 
	include ☞ts:?Relations 
	include ☞ts:?Union 
	include ☞num:?NaturalArithmetics 
    include ☞ts:?SetQuantifiers 

	nodetype : type 
	
	theory dgraph_theory : base:?Logic =
	    nodes : set nodetype 
	    edges : relation nodetype nodetype 

	    successors : nodetype ⟶ set nodetype 
	        = [a] ⟪ nodes | ([x] edges a x) ⟫ 

	    predecessors : nodetype ⟶ set nodetype 
	        = [a] ⟪ nodes | ([x] edges x a) ⟫ 

	    neighbours : nodetype ⟶ set nodetype 
	        = [a] (successors a) ∪ (predecessors a)  

    	n_regular : ℕ ⟶ prop  = [n] ∀ ∈ nodes . [a] ∃= n ∈ (neighbours a) . [b] TRUE 
	

	theory ugraph_theory : base:?Logic = 
		include ☞?Graphs/dgraph_theory 
		undirected_edges : ⊦ symmetric edges 
	

	theory finite_dgraph_theory : base:?Logic =
    	include ☞?Graphs/dgraph_theory 
    	finite : ⊦ nodes finite 
    

    theory finite_ugraph_theory : base:?Logic =
        include ☞?Graphs/ugraph_theory 
        include ☞?Graphs/finite_dgraph_theory 
    

	dgraph : kind  = Mod ☞?Graphs/dgraph_theory  role abbreviation 
	ugraph : kind  = Mod ☞?Graphs/ugraph_theory  role abbreviation 

	finite_dgraph : kind  = Mod ☞?Graphs/finite_dgraph_theory  role abbreviation 
	finite_ugraph : kind  = Mod ☞?Graphs/finite_ugraph_theory  role abbreviation 
	
 	include ☞ts:?RelationClosure 
	
	nodesOf : {g: dgraph}set nodetype  = [g] (g.nodes)  # nodes 1
	dEdgesOf : {g: dgraph}relOn nodetype  = [g] (g.edges)  # edgesOf 1
	uEdgesOf : {g: ugraph}relOn nodetype  = [g] symmetric_closure (g.edges)  # edgesOf 1 

	order : finite_dgraph ⟶ ℕ  = [g] | nodesOf g | 

	include ☞base:?InformalProofs 
	
	inducedUGraph : dgraph ⟶ ugraph  = [d : dgraph] ['
		nodes := d.nodes , 
		edges := symmetric_closure (d.edges) ,
		undirected_edges := trivial
	'] 
	    


theory emptyGraph : base:?Logic = 
  include ?Graphs 
  graphEmpty : dgraph ⟶ bool  = [g] empty (g.nodes) 
  emptyGraph : dgraph  = ['
	  nodes := emptySet nodetype ,
	  edges := ([x : nodetype,y : nodetype] false)
	']  #  
	
	graphEdgeless : dgraph ⟶ bool  = [g] (g.edges) ≐ [x,y] false 
	edgelessGraph : set nodetype ⟶ dgraph  = [S] ['
      nodes := S ,
      edges := ([x : nodetype,y : nodetype] false)
      '] 
	

theory GraphOrderSize : base:?Logic =
  include ?Graphs 
  include ☞ts:?FiniteCardinality 
  order : dgraph ⟶ ℕ  = [g] | nodesOf g |  # | 1 | 
  // TODO: we would need to convert a relation into a set of pairs and count that ❙
  //size : dgraph ⟶ ℕ ❘ = [g] | dedgesOf g | ❘ # || 1 || ❙


theory GraphDegree : base:?Logic =
  include ?Graphs 
  include ☞ts:?FiniteCardinality 

  // indegree : {g : dgraph} (g.nodes) ⟶ ℕ ❘ = [g,n] | ⟪ dedgesOf g | [e] π2 e ≐n  ⟫ | ❘ indeg 2❙
  // outdegree : {g : dgraph} (g.nodes) ⟶ ℕ ❘ = [g,n] | ⟪ dedgesOf g | [e] π1 e ≐n  ⟫ | ❘ outdeg 2❙
  // degree : {g : ugraph} (g.nodes) ⟶ ℕ ❘ = [g,n] | ⟪ dedgesOf g | [e] π1 e ≐n  ⟫ | ❘ degree 2❙

  
theory InitialTerminal : base:?Logic = 
   include ?Graphs 
   // initial : {g : dgraph} (g.nodes) ⟶ bool ❘ = [g,n] ¬∃[e] e ∈ (g.edges) ∧ ∃[m] e m n ❘ # initial 2 ❙
   // terminal : {g : dgraph} (g.nodes) ⟶ bool ❘ = [g,n] ¬∃[e] e ∈ (g.edges) ∧ ∃[m] e n m ❘ # terminal 2 ❙
   // sets =/= types ❙


theory GraphMorphisms :base:?Logic =
    include ?Graphs 

    theory graphMorphism_theory > g1 : ugraph, g2 : ugraph ❘ =
        fun : nodetype ⟶ nodetype 

        morphism_property : ⊦ ∀ ∈ (g1.nodes) . [n1] ∀ ∈ (g1.nodes) . [n2] (g1.edges) n1 n2 ⇒ (g2.edges) (fun n1) (fun n2) 
    

namespace http://mathhub.info/MitM/core/graphs

import base http://mathhub.info/MitM/Foundation 
import ts http://mathhub.info/MitM/core/typedsets 
import num http://mathhub.info/MitM/core/arithmetics 

theory VertexColoredGraphs : base:?Logic =
    include ?Graphs 

    theory vertexcoloredgraph_theory : base:?Logic =
        include ☞?Graphs/ugraph_theory 

        colors :set ℕ  // we assume at most countably many colors indexed by ℕ ❙
        color : nodetype ⟶ asType colors 
    

    theory undirectedVertexcoloredgraph_theory : base:?Logic =
        include ☞?Graphs/ugraph_theory 
        include ☞?VertexColoredGraphs/vertexcoloredgraph_theory 
    


theory EdgeColoredGraphs : base:?Logic =
    include ?Graphs 

    theory edgecoloredgraph_theory : base:?Logic =
        include ☞?Graphs/dgraph_theory 

        colors : set ℕ  // we assume at most countably many colors indexed by ℕ ❙
        colorOf : {a,b:nodetype} ⊦ edges a b ⟶ asType colors  # color 1 2 %I3 


        color_symm_prop : prop  = ∀[a] ∀[b] ∀[p] ∀[q] edges a b ⇒ colorOf a b p ≐ colorOf b a q 
        // TODO needs eliminating the second proof argument ❙
    

    theory undirectedEdgecoloredgraph_theory : base:?Logic =
        include ☞?Graphs/ugraph_theory 
        include ☞?EdgeColoredGraphs/edgecoloredgraph_theory 


        color_symm : ⊦ color_symm_prop 
        proper_prop :prop  = ∀[a] ∀ ∈ (neighbours a) . [b] ∀ ∈ (neighbours a) . [c] ∀[p] ∀[q] b ≠ c ⇒ colorOf a b p ≠ colorOf a c q 
        // TODO needs eliminating the second proof argument ❙
    

    uecGraph : Mod ☞?EdgeColoredGraphs/undirectedEdgecoloredgraph_theory 


    theory properEdgecoloredgraph_theory : base:?Logic =
        include ☞?EdgeColoredGraphs/undirectedEdgecoloredgraph_theory 

        is_proper : ⊦ proper_prop 
    

    properedgecoloredGraph = Mod ☞?EdgeColoredGraphs/properEdgecoloredgraph_theory 

    subGraph : properedgecoloredGraph ⟶ (nodetype ⟶ prop) ⟶ (nodetype ⟶ nodetype ⟶ prop) ⟶ properedgecoloredGraph 
    // TODO definiens ❙
    // TODO generalize ❙

    components: properedgecoloredGraph ⟶ set properedgecoloredGraph 


theory ColoredGraphMorphisms : base:?Logic =
    include ?GraphMorphisms 
    include ?EdgeColoredGraphs 
    include ☞base:?InformalProofs 

    theory colorPreservingMorphism > g1 : uecGraph, g2 : uecGraph ❘ =
        include ☞?GraphMorphisms/graphMorphism_theory g1 g2 

        // preservation_property : ⊦ ∀ ∈ (g1.nodes) . [n1] ∀ ∈ (g1.nodes) . [n2] ∀ [p : ⊦ (g1.edges) n1 n2]
            (g1.colorOf)  n1 n2 p ≐ (g2.colorOf) (fun n1) (fun n2) trivial ❙
    


theory Maniplexes :base:?Logic =
    include ?EdgeColoredGraphs 

    theory maniplex_theory : base:?Logic > rank : ℕ ❘ =
        include ☞?Graphs/ugraph_theory 

        structure colored : ?EdgeColoredGraphs/properEdgecoloredgraph_theory =
            nodes = nodes 
            edges = edges 
            colors @ colors  = ⟪ (fullset ℕ) | ([x] x < rank) ⟫ 
            colorOf @ colorOf 
        

        this : properedgecoloredGraph  // TODO ❙

        is_n_regular : ⊦ n_regular rank 
        subgraph_induced_by_colors : {i : ℕ, j : ℕ} properedgecoloredGraph 
        // TODO ❙

        has_squares_prop : prop  // = ∀ ∈ colors . [i] ∀ ∈ colors . [j] ((max i j) - (min i j)) > 1 ⇒
                                                ∀ ∈ (components (subgraph_induced_by_colors i j)) . [C] ∃= 4 ∈ (C.nodes) . [x] true 

        has_squares : ⊦ has_squares_prop 


        pathIntersection_property : prop 
        // For every pair of nodes (u,v) and every pair of colors (i,j):
            if there is a path (TODO!) from u to v that only uses colors >i and a second path that only uses colors <j,
            then there's a path that only uses colors c with i<c<j

    

    maniplex = [n:ℕ] Mod ☞?Maniplexes/maniplex_theory n 

    dual : {n:ℕ} maniplex n ⟶ maniplex n 
        // swaps edges of color i with edges of color n - 1 - i  

    k_faces : {rank : ℕ} maniplex rank ⟶ ℕ ⟶ set properedgecoloredGraph 
      // = [r,M,k] components (subGraph M ([x] true) ([x,y] (M.color) x y ≠ k)) 

    k_face_flagGraph : {rank : ℕ} maniplex rank ⟶ ℕ ⟶ set properedgecoloredGraph 
        // = [r,M,k] components (subGraph M ([x] true) ([x,y] (M.color) x y < k)) 
    // return type should be set (maniplex k) ❙

    facet : {rank : ℕ} maniplex rank ⟶ set properedgecoloredGraph 
        // = [r,M] k_face_flagGraph r M (r-1) 
    // return type should be set (maiplex rank-1) ❙

    // k_face_flagGraph preserves pathIntersection_property i.e. return type polytopeFlagGraph ❙

    vertex_figures : {rank : ℕ} maniplex rank ⟶ set properedgecoloredGraph 
        = [r,M] k_face_flagGraph r M 0  // ...and shift colors to get maniplex/polytopeFlagGraph again ❙

    theory polytopeFlagGraph_theory : base:?Logic > rank : ℕ ❘ =
        include ☞?Maniplexes/maniplex_theory (rank) 

        hasPathIntersection : ⊦ pathIntersection_property 
    

namespace http://mathhub.info/MitM/core/measures 

import base http://mathhub.info/MitM/Foundation 
import ts http://mathhub.info/MitM/core/typedsets 
import lfx http://gl.mathhub.info/MMT/LFX/Sigma 
import exr http://mathhub.info/MitM/core/arithmetics 
import seq http://cds.omdoc.org/urtheories 
import desc http://mathhub.info/MitM/core/DescriptionOperators

theory Additive : base:?Logic = 
  include arithmetics?ExtendedReals 
  include collections?Properties 
	
  prop_additive : {A : type}{F : collection A} (setastype F ⟶ ℝ) ⟶ bool  # prop_Additive 2 3	
    // = [A,F,f] ∀[S]∀[T] disjoint X Y ⇒ f(X ∪ Y) ≐ f(X) + f(Y)  
    // DM: conversion between sets and types needed to work properly ❙


theory SigmaAdditive : base:?Logic = 
  include ☞ts:?Functions 
  include ?SigmaAlgebra 
  include arithmetics?ExtendedReals 
  include calculus?Series 
	
  prop_sigmaAdditive : {A : type}{F : collection A} (setastype F ⟶ ℝ) ⟶ bool  # prop_sigmaAdditive 2 3	
    // = [A,F,f] ∀[S : sequence (setastype (F.coll))] pairwiseDisjoint (im S (fullset ℕ)) ⇒  f (elem (F.coll) (UNION (im S (fullset ℕ)))) ≐ SUM ([x : ℕ] f (S x)) 
    // DM: conversion between sets and types needed to work properly ❙


theory Measure : base:?Logic =
	include ?SigmaAdditive 
	include calculus?Series 
	include ☞ts:?Functions 
	
	theory measure_theory : base:?Logic > X : type , A : sigmaAlgebra X ❘ =
		measure : setastype (A.coll) ⟶ ℝ  # μ 1 prec 120  
		axiom_nonnegative : ⊦ ∀ [x] μ x ≥ 0 
		axiom_emptyiszero : ⊦ μ  (elem (A.coll) ∅ ) ≐ 0 
		axiom_sigmaadditivity : ⊦ prop_sigmaAdditive (A.coll) measure 
	
	measure = [X : type, A : sigmaAlgebra X] Mod ☞?Measure/measure_theory X A 
	measureSpace = {'
  		universe : type ,
  		sigma_algebra : sigmaAlgebra universe ,
  		rmeasure : measure universe sigma_algebra
	'}
	
	measurableSpace = {'universe : type , sigma_algebra : sigmaAlgebra universe '} 

	// very slow! toMeasureSpace : {ms: measurableSpace} measure (ms.universe) (ms.sigma_algebra) ⟶ measureSpace 
	❘// = [ms, m] ['universe := ms.universe , sigma_algebra := ms.sigma_algebra , measure := m'] ❙
	                                                                         
	isFiniteMeasure : measureSpace ⟶ bool // slow! = [ms] (ms.measure.measure) (elem (ms.sigma_algebra.coll) (fullset (ms.universe))) < ∞



theory PowerSigmaAlgebra : base:?Logic =
	include ?Measure 
	
	prop_powersetIsSigmaAlgebra : type ⟶ bool = [A] prop_isSigmaAlgebra A (powerset A (fullset A))  
	
	prop_fullInPowerset : {A : type} ⊦ prop_fullInColl (℘ (fullset A))  // (℘ (fullset A)) ❙ 
	
	prop_finiteIntersectionPower : {A : type} ⊦ prop_finiteIntersection (℘ (fullset A)) 
  prop_complementsPower : {A : type} ⊦ prop_closedUnderComplements (℘  (fullset A)) 
 // lemma_finiteUnion : ⊦ prop_finiteUnion coll ❘ = sketch "by de Morgan" ❙
//	lemma_empty : ⊦ prop_emptyInColl coll ❘ = sketch "$∅$ is the complement of $X$" ❙ 

	prop_intersectionInPower : {A : type} ⊦ prop_intersectionInColl (℘ (fullset A)) 

	powerSigmaAlgebra : {X : type} sigmaAlgebra X 
	 // = [X : type] [' 	setalgebra/axiom_complements := prop_complementsPower  , coll := ℘  (fullset X), axiom_intersection := prop_intersectionInPower 	
	, setalgebra/axiom_full :=  prop_fullInPowerset  ']  



theory CountingMeasure : base:?Logic =
	include ?PowerSigmaAlgebra 

	
	countingMeasureFunction : {X : type, A : sigmaAlgebra X} setastype (A.coll) ⟶ ℝ
	// slow! = [A, S, s] if s finite  then (| s | : ℝ) else ∞
	
	countingMeasureFunction_nonnegative : {X : type, A : sigmaAlgebra X } ⊦ ∀ [x] (countingMeasureFunction X A) x ≥ 0
// slow!	countingMeasure_emptyiszero	: {A : type, S : sigmaAlgebra A} ⊦ (countingMeasureFunction A S) (elem (S.coll) ∅) ≐ 0 ❙
	countingMeasure_sigmaadditivity : {A : type , S : sigmaAlgebra A} ⊦ prop_sigmaAdditive (S.coll) (countingMeasureFunction A S) 

	countingMeasure : {X : type, A : sigmaAlgebra X}  measure X A  //  =  [X,A] 
	['
	measure := (countingMeasureFunction X A) , axiom_nonnegative :=  countingMeasureFunction_nonnegative ,   
	axiom_emptyiszero := countingMeasure_emptyiszero , axiom_sigmaadditivity := countingMeasure_sigmaadditivity
	'] 
	
	countingMeasurableSpace : type ⟶ measurableSpace  // slow! = [A] ['universe := A , sigma_algebra := powerSigmaAlgebra A']
	countingMeasureSpace : type ⟶ measureSpace  // slow! = [A] ['universe := A , sigma_algebra := powerSigmaAlgebra A , measure := countingMeasure A (powerSigmaAlgebra A)   '] 
                 

theory NullSets : base:?Logic =
	include ?Measure 
  isNullSet : {m : measureSpace} set (m.universe) ⟶ bool // slow! = [m , s] (s ∈ m.sigma_algebra.coll) ∧ (((m.measure.measure) 
  (elem (m.sigma_algebra.coll) s)) ≐ 0)
  allNullSets : {m : measureSpace} collection (m.universe) // slow!= [m] ⟪  (m.sigma_algebra.coll) | ([s] (((m.measure.measure) 
  (elem (m.sigma_algebra.coll) s)) ≐ 0))⟫ 


theory AlmostEverywhere : base:?Logic =
	include ?NullSets 
	
	almostEverywhere : {m : measureSpace} ((m.universe) ⟶ bool) ⟶ bool 
	= [m,P] ∃ [n] n ∈ (allNullSets m) ∧ (∀[x] x ∈ (fullset (m.universe) \ n) ⇒  P x)# AE 1 2 

namespace http://mathhub.info/MitM/core/measures 

import base http://mathhub.info/MitM/Foundation 
import ts http://mathhub.info/MitM/core/typedsets 
import top http://mathhub.info/MitM/core/topology 
import arith http://mathhub.info/MitM/core/arithmetics 

theory SetAlgebra : base:?Logic = 
  include collections?Properties 
  include ☞base:?InformalProofs 

  prop_isSetAlgebra : {G : type} collection G ⟶ prop 
    = [G,C] prop_fullInColl C ∧ prop_closedUnderComplements C ∧ prop_finiteIntersection C 
	  # isSetAlgebra 2 
	  
	theory setAlgebra_theory : base:?Logic > X : type ❘ =
		include typedsets?SetCollection/setColl_theory (X) 
		axiom_full : ⊦ prop_fullInColl coll 
		axiom_finiteIntersection : ⊦ prop_finiteIntersection coll 
		axiom_complements : ⊦ prop_closedUnderComplements coll 
		lemma_finiteUnion : ⊦ prop_finiteUnion coll  = sketch "by de Morgan" 
		lemma_empty : ⊦ prop_emptyInColl coll  = sketch "$∅$ is the complement of $X$"  
	
	setAlgebra = [X : type] Mod ☞?SetAlgebra/setAlgebra_theory X 

    
theory SigmaAlgebra : base:?Logic = 
	include ☞collections?Properties 
	include ☞base:?InformalProofs 
	include ?SetAlgebra 
	
  prop_isSigmaAlgebra : {G : type} collection G ⟶ prop  
	  = [G,C] isSetAlgebra C ∧ prop_intersectionInColl C 
	  # isSigmaAlgebra 2 
	  
	theory sigmaAlgebra_theory : base:?Logic > X : type ❘ =
		include typedsets?SetCollection/setColl_theory (X) 
		
		axiom_intersection : ⊦ prop_intersectionInColl coll 
		lemma_union : ⊦ prop_unionInColl coll  = sketch "by de Morgan" 
		implicit structure setalgebra : ?SetAlgebra/setAlgebra_theory =
			coll = coll 
			axiom_finiteIntersection = sketch "special case of $axiom_intersection$" 
			lemma_finiteUnion = sketch "special case of $lemma_union$" 
		
	
	
	sigmaAlgebra = [X : type] Mod ☞?SigmaAlgebra/sigmaAlgebra_theory X 


theory Measurable : base:?Logic =
  include ☞ts:?Functions 
  include ?SigmaAlgebra 
  
	measurable : {A : type, B : type}{X : sigmaAlgebra A, Y : sigmaAlgebra B} (A ⟶ B) ⟶ prop 
	 = [A,B][X,Y,F] ∀[S] S ∈ (Y.coll) ⇒ (preim F S) ∈ (X.coll) 
	 # measurable 3 4 5 
	 

 
 
theory LebesgueMeasurable : base:?Logic =
	include ?Measurable 
	include ☞arith:?RealArithmetics 

  lebesgueMeasurableLeq : {A : type, s : sigmaAlgebra A} (A ⟶ ℝ) ⟶ bool 
  = [A,s,f] ∀[x : ℝ] ⟪ fullset A | ([i : A] (f i) ≤ x) ⟫ ∈ (s.coll) # lebesgueMeasurableLeq 2 3
  lebesgueMeasurableLt : {A : type, s : sigmaAlgebra A} (A ⟶ ℝ) ⟶ bool 
  = [A,s,f] ∀[x : ℝ] ⟪ fullset A | ([i : A] (f i) < x) ⟫ ∈ (s.coll) # lebesgueMeasurableLt 2 3
  lebesgueMeasurableGeq : {A : type, s : sigmaAlgebra A} (A ⟶ ℝ) ⟶ bool 
  = [A,s,f] ∀[x : ℝ] ⟪ fullset A | ([i : A] (f i) ≥ x) ⟫ ∈ (s.coll) # lebesgueMeasurableGeq 2 3
  lebesgueMeasurableGt : {A : type, s : sigmaAlgebra A} (A ⟶ ℝ) ⟶ bool 
  = [A,s,f] ∀[x : ℝ] ⟪ fullset A | ([i : A] (f i) > x) ⟫ ∈ (s.coll) # lebesgueMeasurableGt 2 3 


// MiKo: would like a view from topological spaces into Sigma Algebras that makes continuous functions measurable. ❚
// I don't understand - in general, sigma algebras aren't topologies... ❚
/T The BorelSigmaAlgebra is the smallest SigmaAlgebra that contains the collection of open sets. ❚
theory BorelSigmaAlgebra : base:?Logic = 
  include ☞ts:?LeastMost 
  include ?SigmaAlgebra 
  include topology?OpenSetTopology 
  
  borelsigmacoll : {A : type} collection A ⟶ collection A  = [A,C] least ([D] isSigmaAlgebra D ∧ (C ⊑ D)) (subset (set A))  # borelsigma 2
 //  axiom_closedundercomplements : {t : topologicalSpace} ⊦ prop_closedUnderComplements (borelsigma (topologyOf t)) ❙
 // axiom_closedunderintersections : {t : topologicalSpace} ⊦  prop_intersectionInColl (borelsigma (topologyOf t)) ❙
  borelSigma : {t : topologicalSpace} sigmaAlgebra (t.universe)  
    // = [t] ['
	  	  coll := borelsigma (topologyOf t) ,
	  	  axiom_full := (t.axiom_full) ,
	  	  axiom_intersection := axiom_closedunderintersections ,
	  	  axiom_complements := axiom_closedundercomplements
	'] 


theory BorelMeasurable : base:?Logic =
	include ?Measurable 
	include ?BorelSigmaAlgebra 
	include ☞top:?RealTopology 
	
	borelMeasurable : {A : type, t : topologicalSpace} sigmaAlgebra A ⟶ (A ⟶ t.universe) ⟶ prop   = [A,t,s,f] measurable s (borelSigma t) f 
	# borelMeasurable 1 2 3 4 
	
	realBorelMeasurable : {A : type} sigmaAlgebra A ⟶ (A ⟶ ℝ) ⟶ prop = [A,s,f] measurable s (borelSigma realTopologicalSpace) f
	
	lemma_realBorelMeasurableIsMeasurable 
	

namespace http://mathhub.info/MitM/core/numbertheory 

import base http://mathhub.info/MitM/Foundation 
import sets http://mathhub.info/MitM/core/typedsets 

theory AdditiveBases : base:?Logic =
    include ☞sets:?FiniteSets 
    include ☞sets:?SetQuantifiers 
    include ☞sets:?LeastMost 
    include ?NatIntervals 

    isAdditiveBasisFor : set ℕ ⟶ set ℕ ⟶ prop 
        = [A,T] ∀ ∈ T . [t] ∃ ∈ A . [a1] ∃ ∈ A . [a2] a1 + a2 ≐ t 

    isRestrictedAdditiveBasisFor : set ℕ ⟶ set ℕ ⟶ prop 
       = [A,T] (isAdditiveBasisFor A T) ∧ (∀ ∈ A . [x:ℕ] ∀ ∈ T . [y:ℕ] (2 ⋅ x) ≤ y) ∧
          ∃ [b] T ≐ natInterval 0 b 

    include ☞sets:?LeastMost 

    isSymmetricAdditiveBasis : set ℕ ⟶ set ℕ ⟶ prop 
        // = [A,T] (isAdditiveBasisFor A T) ∧ ∀ ∈ A . [a] ((greatest ([x:ℕ] x ∈ A) ([x:ℕ,y:ℕ] x ≤ y) - a) ∈ A) ❙

namespace http://mathhub.info/MitM/core/numbertheory 

import base http://mathhub.info/MitM/Foundation 
import sets http://mathhub.info/MitM/core/typedsets 
import arith http://mathhub.info/MitM/core/arithmetics 

theory NatIntervals : base:?Logic =
    include ☞arith:?NaturalArithmetics 
    include ☞sets:?TypedSets 

	natInterval : ℕ ⟶ ℕ ⟶ set ℕ  = [a,b] ⟪ fullset ℕ | ([x] a ≤ x ∧ x ≤ b ) ⟫ 

namespace http://mathhub.info/MitM/core/typedsets 
import base http://mathhub.info/MitM/Foundation 

theory UpDownSet : base:?Logic = 
   include ?POSet 
   upset : {P : poset} (set (P.universe)) ⟶ bool  = [P,F] ∀[x] ∀[y] x ∈ F ∧ (P.ord) x y ⇒ y ∈ F  # upset 2
   downset : {P : poset} (set (P.universe)) ⟶ bool  = [P,F] ∀[x] ∀[y] x ∈ F ∧ (P.ord) y x ⇒ y ∈ F  # downset 2
  

theory filter : base:?Logic = 
  include ?POSet 
  include ?UpDownSet 
  include ?Relations 
  include ?LeastMost 
  include ?DirectedSet
  prop_isFilter : {P : poset} (set (P.universe)) ⟶ bool  = [P,F] upset F ∧ (P.prop_directedSubset) F  # isFilter 2
  prop_isProperFilter : {P : poset}  (set (P.universe)) ⟶ bool  = [P,F] isFilter F ∧ ¬ F ≐ fullset (P.universe) 
  prop_isUltrafilter : {P : poset} (set (P.universe)) ⟶ bool  = [P,F] isGreatest F ([x] isFilter x) ([x,y] subset (P.universe) x y) 

namespace  http://mathhub.info/MitM/core/typedsets 

import base http://mathhub.info/MitM/Foundation 
import sig http://gl.mathhub.info/MMT/LFX/Sigma 


theory FiniteSets : base:?Logic =
	include ☞base:?ProductTypes 
	include ?AllSets 
	

	finiteSet : type ⟶ type  = [t] Σ  x : (set t) . ⊦ x finite # finSet 1 
	
	setToFiniteSet : {A : type , s : set A} ⊦ s finite ⟶ finSet A = [A,s,p] ⟨ s , p ⟩
	
	theorem_emptySetIsFinite : {A : type} ⊦ (∅ : set A) finite
	
	theorem_setConsFinite : {A : type, s : set A , a : A} ⊦ s finite ⟶ ⊦ (s <- a) finite 
	
	theorem_setConsFiniteSplit : {A : type, s : set A , a : A } ⊦ (s <- a) finite ⟶ ⊦ s finite  # setSpFin 2 3 4 // error , wenn keine notation dann fehle rin setsum -> bla ❙

namespace http://mathhub.info/MitM/core/typedsets 
import base http://mathhub.info/MitM/Foundation 

theory Functions : base:?Logic =
	include ?Relations 
	function_composition: {A : type,B : type, C : type} (A ⟶ B) ⟶ (B ⟶ C)  ⟶ (A ⟶ C)  = [A,B,C][f,g] [x] g (f x)  # 5 ° 4 
	image: {A,B} (A ⟶ B) ⟶ set A ⟶ set B   # im 3 4 
	function_restriction: {A : type,B : type, C : type}{prf : (C <* A)} (A ⟶ B) ⟶ (C ⟶ B)  # function_restriction 5 3 
	preimage : {A,B} (A ⟶ B) ⟶ set B ⟶ set A  # preim 3 4 
	identityFunction : {A : type} (A ⟶ A)  = [A,x] x  # Id 1 
  constantFunction : {A : type,B : type} B ⟶ A ⟶ B  = [A,B,c,x] c 


theory Injective : base:?Logic =

	injective : {A : type,B : type, f: A ⟶ B} prop  
		= [A,B,f] ∀[x:A] ∀[y : A]  f x ≐ f y ⇒ x ≐ y 
		# is_injective 3  
		
	           
theory Surjective : base:?Logic =
	surjective : {A : type, B : type, f: A ⟶ B} prop  
		= [A,B,f]   ∀[y : B] ∃[x: A]  f x ≐ y 
		# is_surjective 3  


theory Bijective : base:?Logic = 
	include ?Surjective
	include ?Injective  

	bijective : {A: type, B: type, f : A ⟶ B} prop 
		=  [A, B, f] is_injective f ∧ is_surjective f
		# is_bijective 3 
          
	bijections : {A : type, B : type} type  = [A, B] (A ⟶ B)  # bijections 1 2
	inverseBijections : {A : type, B : type} bijections A B ⟶ bijections B A  # bijinv 3

	   
theory InverseFunction : base:?Logic =
   include ☞base:?DescriptionOperator 
   inverse : {A : type,B: type, f: A ⟶ B} B ⟶ A  
    = [A,B,f,y]  ι [x] f x ≐ y  
    # 1^-1 


theory Permutation : base:?Logic = 
   include ?Bijective 
   permutation : {A: type, f: A ⟶ A} prop 
     = [A,f] is_bijective f 
     # is_permutation 2 

namespace http://mathhub.info/MitM/core/typedsets 
import base http://mathhub.info/MitM/Foundation 
import ar http://mathhub.info/MitM/core/arithmetics 

theory PrOSet : base:?Logic = 
	include ?Relations 
	include ☞base:?NaturalDeduction 
	include ☞base:?InformalProofs 
	include ?AllSets 
	
  theory proset_theory : base:?Logic = 
     include ?SetStructures/setstruct_theory 
     ord : U ⟶ U ⟶ bool  # 1  2  prec 5 
     axiom_reflexive : ⊦ reflexive ord 
     axiom_transitive : ⊦ transitive ord 
     lemma_preOrder : ⊦ preOrder ord  = and_introduction axiom_reflexive axiom_transitive 
     strictord : U ⟶ U ⟶ bool  = [a,b] ord a b ∧ ¬ a ≐ b  # 1  2 prec 5 
     strict_lemma : ⊦ strictPreOrder strictord  = sketch "by construction" 
     
     prop_upperBound : set U ⟶ U ⟶ bool  = [S,b] ∀[s] S s ⇒ (s ≼ b) 
     prop_lowerBound : set U ⟶ U ⟶ bool  = [S,b] ∀[s] S s ⇒ (b ≼ s) 
     prop_directed : bool  = ∀[a] ∀[b] ∃[c] a ≼ c ∧ b ≼ c 
     prop_directedSubset : (U ⟶ bool) ⟶ bool  = [F] ∀[a] ∀[b] F a ∧ F b ⇒ ∃[c] F c ∧ a ≼ c ∧ b ≼ c 
   
  proset = Mod ☞?PrOSet/proset_theory  role abbreviation 
  

theory LeastMost : base:?Logic = 
   include ☞base:?DescriptionOperator 
   include ?Relations 
	include ?AllSets 
	
    prop_isLeast : {A : type} A ⟶ (A ⟶ bool) ⟶ (A ⟶ A ⟶ bool) ⟶ bool  = [A,x,P,R] P x ∧ ∀[y] P y ⇒ R x y  # isLeast 2 3 4  
    least : {A : type} (A ⟶ bool) ⟶ (A ⟶ A ⟶ bool) ⟶ A  = [A,P,R] ι [x] isLeast x P R  # least 2 3   
    prop_isGreatest : {A : type} A ⟶ (A ⟶ bool) ⟶ (A ⟶ A ⟶ bool) ⟶ bool  = [A,x,P,R] isLeast x P (converse R)  # isGreatest 2 3 4  
    greatest : {A : type} (A ⟶ bool) ⟶ (A ⟶ A ⟶ bool) ⟶ A  = [A,P,R] ι [x] isGreatest x P R  # greatest 2 3
    // least/greatest assume that there is a unique least element. Instead minimal/maximal return a set of minimal elements (a singleton
    // if there is a unique one). ❙
    minimal: {A : type} (A ⟶ bool) ⟶ (A ⟶ A ⟶ bool) ⟶ set A  = [A,P,R] ι [s] ∀[x] x ∈ s ⇒ isLeast x P R  # minimal 2 3
    maximal: {A : type} (A ⟶ bool) ⟶ (A ⟶ A ⟶ bool) ⟶ set A  = [A,P,R] ι [s] ∀[x] x ∈ s ⇒ isGreatest x P R  # maximal 2 3
    


theory DirectedSet : base:?Logic =
	include algebra?OperationProps 
	include ☞base:?InformalProofs 
	include ?LeastMost 
	include ?PrOSet 
	
	theory directedSet_theory : base:?Logic =
   		include ?PrOSet/proset_theory 
   		lub : set U ⟶ U  = [S] least (prop_upperBound S) ord 
   		glb : set U ⟶ U  = [S] greatest (prop_lowerBound S) ord 
   		meet : U ⟶ U ⟶ U  = [a,b] lub [x] x ≐ a ∧ x ≐ b 
   		join : U ⟶ U ⟶ U  = [a,b] glb [x] x ≐ a ∨ x ≐ b 
      axiom_directed : ⊦ prop_directed 
   		meetIdenpotent : ⊦ prop_idempotent meet  =  sketch "by idempotence of conjunction" 
   		meetAssociative : ⊦ prop_associative meet  = sketch "by associativity of conjunction" 
   		meetCommutative : ⊦ prop_commutative meet  = sketch "by commutativity of conjunction" 
   		joinIdempotent : ⊦ prop_idempotent join  =  sketch "by idempotence of disjunction" 
   		joinAssociative : ⊦ prop_associative join  = sketch "by associativity of disjunction" 
   		joinCommutative : ⊦ prop_commutative join  = sketch "by commutativity of disjunction" 
   
   directedSet = Mod ☞?DirectedSet/directedSet_theory  role abbreviation 


theory Fixpoints : base:?Logic =
	include ?AllSets 
	isFixpoint: {A:type, f:A ⟶ A, a:A} prop  = [A,f,a] f a  ≐  a 
	fixpoints: {A:type} (A ⟶ A) ⟶ set A  = [A,f] ι [s] ∀[x] x ∈ s ⇒ isFixpoint A f x 


theory POSet : base:?Logic = 
  include ?PrOSet 
  
  theory poset_theory : base:?Logic = 
     include ?PrOSet/proset_theory 
     axiom_antisymmetric : ⊦ antisymmetric ord 
     lemma_partialOrder : ⊦ partialOrder ord  = and_introduction lemma_preOrder axiom_antisymmetric
     strict_lemma : ⊦ strictPartialOrder strictord  = sketch "by construction" 
  
  poset = Mod ☞?POSet/poset_theory  role abbreviation 


theory SupremumReal : base:?Logic =
	include ?AllSets 
	include ?LeastMost 
	include ☞ar:?ExtendedReals 
		
	supremumReal : set ℝ ⟶ ℝ= [s] least ([a] ∀[x] x ∈ s ⇒ x ≤ a)  ([a,b] a ≤ b)   # supR 1 

namespace http://mathhub.info/MitM/core/typedsets 
import base http://mathhub.info/MitM/Foundation 

/T MiKo: a first-order approximation of a view from POSet to PowerSet
   eventually, we want to push filter and co out over this to get the 
   usual applications of filters ❚

theory ASet : base:?Logic =
   include ?PowerSet 
   include ?BasicLemmata 
   A : type 
 

theory PowersetPOSet : base:?Logic =
	include ?POSet 

	view PowersetIsPOSet : ?POSet/poset_theory -> ?ASet =
    	universe = set A 
    	ord = [S,T] subset A S T 
    	axiom_reflexive = lemma_subsetReflexive 
    	axiom_transitive = lemma_subsetTransitive 
    	axiom_antisymmetric = lemma_subsetAntisymmetric 
    

namespace http://mathhub.info/MitM/core/typedsets 
import arith http://mathhub.info/MitM/core/arithmetics 
import base http://mathhub.info/MitM/Foundation 

theory Relations : base:?Logic =
	include ☞arith:?NaturalArithmetics 
	include ?TypedSets 
	include ☞base:?ProductTypes 
	
	relation : type ⟶ type ⟶ type  = [A,B] A ⟶ B ⟶ bool  # relation 1 2  
	relOn : type ⟶ type  = [A] A ⟶ A ⟶ bool  # relOn 1  
	
	converse: {A,B} relation A B ⟶ relation B A  = [A,B][R] [y,x] R x y # converse 3 
	relation_composition: {A,B,C} relation A B ⟶ relation B C  ⟶ relation A C  = [A,B,C][R,S] [x,y] ∃[w] R x w ∧ S w y  # 4 ^ 5 
	range: {A,B} relation A B ⟶ set B  # range 3 
	// restriction: {A,B} relation A B ⟶ {C} relation C B  ❘ # 3 | 4 ❙
	prop_reflexive: {A} relOn A⟶ bool  = [A][R] ∀[x] R x x # reflexive 2 
	prop_irreflexive: {A} relOn A⟶ bool  = [A][R] ∀ [x] ¬ R x x # irreflexive 2 
	prop_symmetric: {A} relOn A⟶ bool  = [A][R] ∀[x]∀[y] R x y ⇒ R y x # symmetric 2 
	prop_antisymmetric: {A} relOn A⟶ bool  = [A][R] ∀[x]∀[y] R x y ∧ R y x ⇒ x ≐ y # antisymmetric 2 
	prop_asymmetric: {A} relOn A⟶ bool  = [A][R] ∀[x]∀[y] R x y ⇒ ¬ R y x  # asymmetric 2 
	prop_total: {A} relOn A⟶ bool  = [A][R] ∀[x]∀[y] x ≠ y ⇒ (R x y ∨ R y x) # total 2 
	prop_transitive: {A} relOn A⟶ bool  = [A][R] ∀[x]∀[y]∀[z] R x y ∧ R y z ⇒ R x z # transitive 2 
	prop_equivalent: {A} relOn A⟶ bool  = [A][R] (symmetric R) ∧ (transitive R) ∧ (reflexive R)  # equivalent 2 
	prop_preorder: {A} relOn A⟶ bool  = [A][R] (reflexive R) ∧ (transitive R)  # preorder 2 
	// MiKo: I could not find any evidence for this name on the web
	prop_permutation: {A} relOn A⟶ bool ❘ = [A][R] (symmetric R) ∧ (transitive R) ❘ # permutation 2 ❙
	prop_commutes: {A} relOn A⟶ relOn A⟶ bool  = [A,f,g] ∀ [x:A] ∀ [y:A] f x y ⇒ (∀ [z:A] g z y ⇒ ∃ [w:A] g w x ∧ f z w)   # 2 commute 3 
	prop_preOrder: {A} relOn A⟶ bool  = [A][R] (reflexive R) ∧ (transitive R)  # preOrder 2 
	prop_strictPreOrder: {A} relOn A⟶ bool  = [A][R] (irreflexive R) ∧ (transitive R)  # strictPreOrder 2 
    prop_partialOrder: {A} relOn A⟶ bool  = [A][R] (preOrder R) ∧ (antisymmetric R)  # partialOrder 2 
	prop_strictPartialOrder: {A} relOn A⟶ bool  = [A][R] (irreflexive R) ∧ (transitive R)  # strictPartialOrder 2 
	prop_order: {A} relOn A⟶ bool  = [A][R] (partialOrder R) ∧ (total R)  # order 2 
	prop_strictOrder: {A} relOn A⟶ bool  = [A][R] (strictPartialOrder R) ∧ (total R)  # strictOrder 2 
    prop_linearOrder: {A} relOn A⟶ bool  = [A][R] (partialOrder R) ∧ ∀ [a] ∀ [b] R a b ∨ R b a  # linearOrder 2 
    prop_wellfounded: {A} relOn A⟶ bool  = [A][R] (partialOrder R) ∧ ∀ [B: set A] ∃ [b] b ∈ B ∧ ∀ [c] (R b c)   # wellfounded 2 
    prop_wellOrder: {A} relOn A⟶ bool  = [A][R] (linearOrder R) ∧ (wellfounded R)   # wellOrder 2 
	// sameRelation: {A,B} relation A B ⟶ relation A B ⟶ bool ❘ = [A,B,f,g] (inclusion f g) ∧ (inclusion f g) ❘ # sameRelation 3 4 ❙
	
  	subrelation : {A,B} relation A B ⟶ relation A B ⟶ bool  = [A,B][R,S] ∀ [x]∀[y] (R x y) ⇒ (S x y)  # 3 sub 4 


theory RelationClosure : base:?Logic = 
  include ?Relations 
  include ?SetRelations 
  include ☞base:?DescriptionOperator 
  
  /T maybe factor out minimal-such-that? ❙
  closure :  {A} relOn A⟶ (relOn A⟶ bool) ⟶ relOn A
  	= [A,R,P] ι [S] R sub S ∧ P S ∧ ∀[T] (R sub T ∧ P T) ⇒ (S ≐ T)  # closure 2 3 
	symmetricClosure : {A} relOn A⟶ relOn A = [A,R] closure R [x] symmetric x  # symmetric_closure 2 
	reflexiveClosure : {A} relOn A⟶relOn A =  [A,R] closure R [x] reflexive x 
	transitiveClosure : {A} relOn A⟶relOn A =  [A,R] closure R [x] transitive x 
  reflexiveTransitiveClosure  : {A} relOn A⟶ relOn A = [A,R] closure R [r] reflexive r ∧ transitive r  # 1^* 
  closureLemma : {A} ⊦ ∀[P : relOn A⟶ bool] ∀[R : relOn A] P (closure R P) 
  
  
// theory QuotientSpace : base:?Logic = 
  include ?Relations ❙
  include ?PowerSet ❙
  include collections?Properties ❙
 
  // temporary workaround; use https://github.com/UniFormal/MMT/issues/358 later. ❙
  equivRel : type ❘ = {A} relOn A ❙
  equivalenceClass : {A} equivRel A ⟶ A ⟶ set A ❘ 
    = [A,R,a] ⟪ (fullset A) | ([x] R a x) ⟫ ❘
    # 3 _^ 2 ❙
  quotient : {A} set A ⟶ equivRel A ⟶ set (set A) ❘
    = [A,S,R] ⟪ (℘ (fullset A)) | ([T] ∀[x] x ∈ T ⇒ ∃[y] y ∈ S ∧ R x y) ⟫ ❘
    # 3 / 2 ❙
  projection : {A} equivRel ⟶ A ⟶ set A ❘
     = [A,R] [a] a _^ R ❘
    # π_2 ❙
  lemma_cover : {A} ⊦ ∀[R] ∀[S] S / R covers S ❙
  lemma_disjiont : {A} ⊦ ∀[R] ∀[S] ∀[X] ∀[Y] X ∈ S / R ∧ Y ∈ S ⇒ disjoint X Y ❙
  lemma_nonEmpty : {A} ⊦ ∀[R] ∀[S] ∀[X] X ∈ S / R ⇒ nonEmpty X ❙

   
// Views to parametric theories are currently impossible; semantics is unclear ❙
// view PartitionQuotientspace : ?Partition -> ?Quotientspace  (R) =
  coll = quottientspace R ❙
  axiom_covers =  lemma_cover ❙
  axiom_nonEmpty =  lemma_nonEmtpy ❙
  axiom_pairwisedisjoint = lemma_disjoint ❙

   
namespace  http://mathhub.info/MitM/core/typedsets 

import base http://mathhub.info/MitM/Foundation 
import ts http://mathhub.info/MitM/core/typedsets 
import sig http://gl.mathhub.info/MMT/LFX/Sigma 
import ar http://mathhub.info/MitM/core/arithmetics 

theory SetSum : base:?Logic =
	include ☞ar:?RealArithmetics 
	include ☞ts:?FiniteSets 

	
	setSum : {A : type  , s : set ℝ} ⊦ s finite ⟶ (A ⟶ ℝ) ⟶ ℝ # setSum 2 3 4 
	setSum_empty : {A : type , f : A ⟶ ℝ} ⊦ setSum ∅ theorem_emptySetIsFinite f ≐ (0 : ℝ) 
	
	setSum_cons : {A : type , s : set ℝ ,  a : ℝ, p : ⊦ (s <- a) finite , f : A ⟶ ℝ} 
	⊦ setSum (s <- a) p f ≐ a + setSum s (theorem_setConsFiniteSplit ℝ s a p) f 

namespace http://mathhub.info/MitM/core/typedsets 
import base http://mathhub.info/MitM/Foundation 
import arith http://mathhub.info/MitM/core/arithmetics 

theory TypedSets : base:?Logic =
  include ☞base:?Lists 
  include ☞base:?Subtyping 
  /T the type operator of sets along with its constructors ❙
  set: type ⟶ type  = [A] A ⟶ prop 

  setCons: {A} A ⟶ set A ⟶ set A  = [A] [a,P] [x] P x ∨ x ≐ a # 3 <- 2 
  setList : {A} List A ⟶  set A  #  2  
  inSet : {A : type} A ⟶ set A ⟶ prop  = [A][a,P] P a  # 2  3 
  bsetst : {A} set A ⟶ (A ⟶ prop) ⟶ set A  = [A][P,Q] [x] P x ∧ Q x  #  2 | 3  
  fullset : {A} set A  = [A] [x] true  # fullset 1 
  setAsType : {A: type, P: set A} type  = [A,P] ⟨ x : A | ⊦ P x ⟩  # asType 2 
   // TODO, need a lot of congruence rules that make sure that setcons ACI ❙


theory SetQuantifiers : base:?Logic =
  include ☞base:?NatLiterals 
  include ?TypedSets 

  forall_sets : {A: type } set A ⟶ (A ⟶ prop) ⟶ prop 
    = [A,S,P] ∀[x:A] x ∈ S ⇒ P x  #   2 . 3 prec -101 
  exists_sets : {A: type } set A ⟶ (A ⟶ prop) ⟶ prop 
    = [A,S,P] ∃[x:A] x ∈ S ∧ P x  #   2 . 3 prec -101 
  exists_n_sets : {A:type} ℕ ⟶ set A ⟶ (A ⟶ prop) ⟶ prop  # ∃= 2  3 . 4 prec -102 


theory EmptySet : base:?Logic =
	 include ?TypedSets 
  emptySet : {A} set A  = [A] [x] false#  %I1 
  empty : {A} set A ⟶ prop 
         = [A,s] s ≐ ∅   # empty 2 
  nonEmpty : {A} set A ⟶ prop 
         = [A,s] s ≠ ∅  
         
  inhabited : {A} set A ⟶ prop  # inhabited 2 
  axiom_inhabited : {A} ⊦ ∀[S:set A] inhabited S ⇔ (∃ [x] (x ∈ S)) 
  axiom_emptySet : {A} ⊦ ¬ (∃ [x:A] (x ∈ ∅)) 


theory Singleton : base:?Logic =
   include ?EmptySet 
   single : {A} A ⟶ set A  = [A,a] ∅ <- a  # single 2 
   singleton : {A} set A ⟶ prop  = [A,s] ∃[x] s ≐ single x  # singleton 2 


  // consider merge this with singleton ❚
theory Tuples : base:?Logic =
	 include ?EmptySet 
	 double : {A} A ⟶ A ⟶ set A  = [A,a,b] ∅ <- a <- b  # double 2 3 
	 triple : {A} A ⟶ A ⟶ A ⟶ set A  = [A,a,b,c] ∅ <- a <- b <- c  # triple 2 3 4 


theory Union : base:?Logic =
   include ?TypedSets 
   include ☞base:?DescriptionOperator 
   
   axiom_union : {A,a : set A, b : set A} ⊦ ∃! [x: set A] ∀[y : A] y ∈ x ⇔ (y ∈ a ∨ y ∈ b) # axiom_union 1 2 3
   union : {A} set A ⟶ set A ⟶ set A  # 2  3  = [A,a,b] 
   		that (set A) ([x: set A] ∀[y : A] y ∈ x ⇔ (y ∈ a ∨ y ∈ b)) (axiom_union A a b) 
   		
   munionCollection:  {A,B} set A ⟶ (A ⟶ set B) ⟶ set B  #  3 4
   unionCollection : {A} set (set A) ⟶ set A  = [A, s] ⋃ s ([e] e)  # UNION 2 

   
theory Intersection : base:?Logic =
   include ?TypedSets 
   
   intersection : {A} set A ⟶ set A ⟶ set A  # 2  3  = [A,a,b] ⟪ a | ([x] x ∈ b) ⟫ 
   
   mintersectCollection : {A,B} set A ⟶ (A ⟶ set B) ⟶ set B  #  3 4 
   intersectCollection : {A} set (set A) ⟶ set A  = [A, s] ⋂ s ([e] e)  # INTERSECT 2 

 
theory SetRelations : base:?Logic =
   include ?Intersection 
   include ?EmptySet 
   
   subset : {A} set A ⟶ set A ⟶ prop  = [A,S,T] ∀[x] x ∈ S ⇒ x ∈ T  # 2  3 
   properSubset : {A} set A ⟶ set A ⟶ prop = [A,S,T] (S ⊑ T) ∧ ¬ S ≐ T  # 2  3 
   superset : {A} set A ⟶ set A ⟶ prop  = [A,S,T] ∀[x] x ∈ T ⇒ x ∈ S  # 2  3 
   properSuperset : {A} set A ⟶ set A ⟶ prop = [A,S,T] (S ⊒ T) ∧ ¬ S ≐ T  # 2  3 
   disjoint : {A} set A ⟶ set A ⟶ prop = [O,A,B] A ∩ B ≐ ∅  # disjoint 2 3 
   
   sameSet : {A} set A ⟶ set A ⟶ prop  = [A,S,T] (S ⊑ T) ∧ (T ⊑ S)   # same_set 2 3 


theory PowerSet : base:?Logic =
	include ?TypedSets 
	powerset : {A} set A ⟶ set (set A) #  2 
	// TODO ❙

   

theory SetDifference : base:?Logic =
	include ?Singleton 
	include ?Union 
	
	setdiff : {A} set A ⟶ set A ⟶ set A = [O,A,B] ⟪ A | ([x] ¬ x ∈ B) ⟫  # 2 \ 3 
	symdiff : {A} set A ⟶ set A ⟶ set A = [O,A,B] (A \ B) ∪ (B \ A)  # 2 symdiff 3 
	complement : {A} set A ⟶ set A = [O,A] (fullset O \ A)  # compl 2 
	// take out an element from a set ❙
	subtract : {A} set A ⟶ A ⟶ set A = [O,A,a] A \ (single a)  # 2 - 3 
 
 
theory BasicLemmata : base:?Logic =
	include ?SetDifference 
	include ?SetRelations 
   
	lemma_extensionality: {A} ⊦ ∀[a:set A] ∀[b:set A] same_set a b ⇔ a ≐ b 
	lemma_universeMember : {A} ⊦ ∀ [a : A] (a ∈ (fullset A)) 
	lemma_subsetTransitive : {A} ⊦ ∀ [s : set A] ∀ [t : set A] ∀ [u : set A] (subset A s t ∧ subset A t u) ⇒ subset A s u 
	lemma_subsetReflexive : {A} ⊦ ∀ [s : set A] subset A s s 
	lemma_subsetAntisymmetric : {A} ⊦ ∀ [s : set A] ∀ [t : set A] (subset A s t ∧ subset A t s) ⇒ s ≐ t 
	lemma_emptyset : {A} ⊦ ∀ [s : set A] subset A ∅ s 
	lemma_emptySetSubset : {A} ⊦ ∀ [s : set A] ( subset A s ∅) ⇒ s ≐ ∅ 
	lemma_properSubsetTransitive : {A} ⊦ ∀ [s : set A] ∀ [t : set A] ∀ [u : set A] (s ⊂ t ∧ t ⊂ u) ⇒ s ⊂ u 
	lemma_properSubsetIrreflexive : {A} ⊦ ∀ [s : set A] ¬ (s ⊂ s) 

   
theory FiniteCardinality : base:?Logic =
	include ?TypedSets 
	include arithmetics?NaturalNumbers 
	
	finite : {A} set A ⟶ prop # 2 finite 
	cardinality : {A, a : set A}⊦ a finite ⟶ ℕ # | 2 | %I3 
	infinite : {A} set A ⟶ prop = [A,S] ¬ S finite  # 2 infinite 


theory SetStructures : base:?Logic =

	theory setstruct_theory : base:?Logic =
		universe : type  # U
	
	setstruct = Mod ☞?SetStructures/setstruct_theory  role abbreviation
	 
	include ?TypedSets 

	dom : setstruct ⟶ type  = [S] (S.universe)  role abbreviation
	doms : {S : setstruct}set (dom S)  = [S] fullset (dom S)  role abbreviation 


theory IndicatorFunction :  base:?Logic =
	include ?TypedSets 
	include ☞arith:?NaturalNumbers 
	include ☞base:?DescriptionOperator 
	indicatorFunction : {A : type} set A ⟶ A ⟶ ℕ = [A,s,a] if (a ∈ s) then (1 : ℕ) else 0  



theory AllSets : base:?Logic =
	include ?FiniteCardinality 
	include ?PowerSet 
	include ?Union 
	include ?SetDifference 
	include ?SetStructures 
	include ?SetRelations 

	typeof : {A} set A ⟶ type // = [A,s] ⟨ x : A | ⊦ x ∈ s⟩  # setastype 2 
	elemof : {A}{s : set A, e : A} ⊦ e ∈ s ⟶ setastype s  # elem 2 3 %I4

 
theory SetCollection : base:?Logic =
   include ?AllSets 

   collection : type ⟶ type  = [G] set (set G)
                                      
   theory setColl_theory : base:?Logic > X : type ❘ =
   	  coll : collection X 
   	  colltype = setastype coll 
   
   setColl = [X : type] Mod ☞?SetCollection/setColl_theory (X) 
   
   emptySetInType : {T, S : setColl T, emptyincoll : ⊦ ∅ ∈ (S.coll) } S.colltype  # ∅t %I1 %I2 %I3 
   fullSetInType : {T, S : setColl T, fullincoll : ⊦ (fullset T) ∈ (S.coll) } S.colltype  # fullt %I1 %I2 %I3 


theory TaggedSetCollection : base:?Logic =
	include ?SetCollection 
	include ☞base:?ProductTypes 
	
	taggedCollection : type ⟶ type = [G] set (G × set G) 


namespace http://mathhub.info/MitM/core/topology 
import base http://mathhub.info/MitM/Foundation 
import sets http://mathhub.info/MitM/core/typedsets 

theory neighborhoodSystem : base:?Logic =
    include sets:?filter 

    universe : type  # X 
    nhsys : X ⟶ powerset (set X)  # N 
    axiom_filter : ⊦ ∀ [x] isFilter (N x) // maybe better use a predicate subtype for N? ❙
    axiom_nhsys1 :  ⊦ ∀ [x] ∀ [U] U ∈ (N x) ⇒ x ∈ U 
    axiom_nhsys2 : ⊦ ∀ [x] ∀ [U] U ∈ (N x) ⇒ ∃ [V] (N x) ∧ ∀ [y] y ∈ V ⇒ U ∈ (N y) 
    isOpen : (set X) ⟶ bool  = [S]  ∀ [x] x ∈ S ⇒ ∃ [U] U ∈ (N x) ∧ U ⊑ S


// view topologyFromNHsystem: ?topology_theory -> ?neighborhoodSystem =
//   universe := universe ❙
//   topology := isOpen ❙

namespace http://mathhub.info/MitM/core/topology 
import base http://mathhub.info/MitM/Foundation 
import calc http://mathhub.info/MitM/core/calculus 

theory RealTopology : base:?Logic =
	include ☞calc:?RealMetricSpace
	include ☞calc:?MetricSpaceAsTopology 
	include ?OpenSetTopology 
	

	realTopology = metricAsTopology realmetricspace  : topology ℝ
	realTopologicalSpace = [' universe := ℝ , topology := realTopology  '] : topologicalSpace 

namespace http://mathhub.info/MitM/core/topology 
import base http://mathhub.info/MitM/Foundation 
import ts http://mathhub.info/MitM/core/typedsets 

theory OpenSetTopology : base:?Logic = 
	include collections?Properties 

	prop_isTopology : {G : type} collection G ⟶ prop  
	  = [G,C] prop_emptyInColl C ∧ prop_fullInColl C ∧ prop_unionInColl C ∧ prop_finiteIntersection C 
	  # isTopology 2 
   
	theory topology_theory : base:?Logic > X : type ❘ =
		include typedsets?SetCollection/setColl_theory (X) 
		axiom_empty : ⊦ prop_emptyInColl coll 
		axiom_full : ⊦ prop_fullInColl coll 
		axiom_union : ⊦ prop_unionInColl coll 
		axiom_intersection: ⊦ prop_finiteIntersection coll 
	
	
	topology = [X : type] Mod ☞?OpenSetTopology/topology_theory (X)
	topologicalSpace : kind  = {'
		universe : type ,
		topology : topology universe
	'}
   
	topologyOf : {G: topologicalSpace} collection (G.universe)  = [G] (G.topology).coll  # topologyOf 1 
   
	isOpen : {G : topologicalSpace} set (G.universe) ⟶ prop  = [G,S] S ∈ (topologyOf G)  # open 2
	isClosed : {G : topologicalSpace} set (G.universe) ⟶ prop = [G,S] ((doms G)\ S) ∈ (topologyOf G)  # closed 2
	isClopen : {G : topologicalSpace} set (G.universe) ⟶ prop  = [G,S] closed S ∧ open S  
	



theory coarsefineTopology : base:?Logic = 
  include ?OpenSetTopology 
  coarserTopology : {A} collection A ⟶ collection A ⟶ prop  = [A,T1,T2] T1 ⊑ T2 
  finerTopology : {A} collection A ⟶ collection A ⟶ prop  = [A,T1,T2] T2 ⊑ T1 
 

theory TrivialTopology : base:?Logic = 
  include ?OpenSetTopology 
  include ☞base:?InformalProofs 
  
  trivialTopology : {A : type} collection A  // = [A] setList (set A) ((emptySet A) , ((fullset A) , nil A))  # trivialTopology 1 
	lemma_empty : {A} ⊦ prop_emptyInColl (trivialTopology A)  = [A] sketch "by construction"  # lemma_empty 1
	lemma_full : {A} ⊦ prop_fullInColl (trivialTopology A)  = [A] sketch "by construction"  # lemma_full 1
	lemma_union : {A} ⊦ prop_unionInColl (trivialTopology A)  = [A] sketch "by construction"  # lemma_union 1
	lemma_intersection: {A} ⊦ prop_finiteIntersection (trivialTopology A)  = [A] sketch "by construction"  # lemma_intersection 1

  indiscreteSpace : {A : type} topologicalSpace  // = [A] [' 
      universe := A , 
      topology := trivialTopology A,
      axiom_empty := lemma_empty A,
      axiom_full := lemma_full A,
      (axiom_union) := lemma_union A,
      axiom_intersection := lemma_intersection A
      '] 
  // ^ "x.topology" still needs to be the record
  	containing the collection and all the proofs. The topological space only contains the universe and the topology (which is a record itself). ❙


theory DiscreteSpace : base:?Logic =
   include ?OpenSetTopology 
   include ☞base:?InformalProofs 
   
   discreteTopology : {A} set A ⟶ collection A  = [A,S] ℘ S 
 	// lemma_empty : {A : type } ⊦ ∀[S : set A] prop_emptyInColl (discreteTopology S) ❘ = sketch "by construction" ❙
	// lemma_full : ⊦ ∀[S] prop_fullInColl (discreteTopology S) ❘ sketch "by construction" ❙
	// lemma_union : ⊦ ∀[S] prop_unionInColl (discreteTopology S) ❘ sketch "by construction" ❙
	// lemma_intersection: ⊦ ∀[S] prop_finiteIntersection (discreteTopology S) sketch "by construction" ❙
		
    // discreteSpace : {A} set A ⟶ topologicalSpace A ❘ = [A,S] ['
	universe := A, 
	topology := ℘ S 
	axiom_empty := lemma_empty A,
	axiom_full := lemma_full A,
        axiom_union := lemma_union A,
        axiom_intersection := lemma_intersection A
  	'] ❙
   
   
theory ClosureInterior : base:?Logic = 
  include ?OpenSetTopology 
   closure : {G : topologicalSpace} set (G.universe) ⟶ set (G.universe) 
    = [G,S] ⋃ ⟪ topologyOf G | ([T] closed T ∧ S ⊑ T) ⟫ ([T] T)  # closure 2
   interior : {G : topologicalSpace} set (G.universe) ⟶ set (G.universe)
    = [G,S] ⋂ ⟪ topologyOf G | ([T] open T ∧ T ⊑ S) ⟫ ([T] T)  # interior 2 
   boundary : {G : topologicalSpace} set (G.universe) ⟶ set (G.universe) 
    = [G,S] closure S \ interior S  # boundary 2
                                                               
   
theory Neighborhood : base:?Logic = 
  include ?OpenSetTopology 
  neighborhood : {G : topologicalSpace} (G.universe) ⟶ set (G.universe) ⟶ prop 
    = [G,a,S] S ∈ topologyOf G ∧ a ∈ S  # neighborhood 3 2
  

theory LimitPoint : base:?Logic = 
  include ?Neighborhood 
  limitPoint : {G : topologicalSpace} (G.universe) ⟶ set (G.universe) ⟶ prop 
    = [G][a,S] S ⊑ doms G ∧ a ∈ S ∧ ∀[N : set (dom G)] neighborhood N a ⇒ ∃[b] b ∈ N ∧ ¬ a ≐ b 
  

theory Continuity : base:?Logic = 
  include ?Neighborhood 
  include ☞ts:?Functions 
  // continuous_def : the preimage of an open set is open ❙
  continuous : {X : topologicalSpace, Y : topologicalSpace} ((dom X) ⟶ (dom Y)) ⟶ prop  
     = [X,Y,f] ∀[O] O ∈ topologyOf X ⇒ (im f O) ∈ topologyOf Y 
      # continuous 3 
  continuousAt : {X : topologicalSpace, Y : topologicalSpace} ((dom X) ⟶ (dom Y)) ⟶ (dom X) ⟶ prop  
     = [X,Y,f,x] ∀[V] neighborhood V (f x) ⇒ neighborhood (preim f V) x
      # continuousAt 3 4 
  

theory Compactness : base:?Logic = 
  include ?OpenSetTopology 
  // compact_def: every open cover C of dom G has a finite subcover D of dom G ❙
  compact : {G : topologicalSpace} prop  = [G] ∀[C] C covers (fullset (G.universe)) ⇒ ∃[D] D subcover C on (fullset (G.universe))  # compact 1 
  
  
theory TopologyBase : base:?Logic = 
  include ?OpenSetTopology 
  base : {X: topologicalSpace}collection (X.universe) ⟶prop  = [G,B] ∀[O] O ∈ topologyOf G ⇒ ∃[C] C ⊑ B ∧ O ≐ UNION C  # 2 basefor 1
  
  
theory HausdorffTopology : base:?Logic = 
   include ?OpenSetTopology 
   include typedsets?SetRelations 
   hausdorffProperty : {G : type}(collection G) ⟶ prop 
     = [G,T] ∀[p] ∀ [q] p ∈ (fullset G) ∧ q ∈ (fullset G) ∧ p ≠ q ⇒ 
       ∃[P]∃[Q]P ∈ T ∧ Q ∈ T ∧ p ∈ P ∧ q ∈ Q ∧ disjoint P Q  role abbreviation 
       
   theory hausdorff_theory : base:?Logic > X : type ❘ =
   	 include ?OpenSetTopology/topology_theory (X) 
   	 ishausdorff : ⊦ hausdorffProperty X coll 
   
   hausdorffTopology : type ⟶ type  = [X : type] Mod ☞?HausdorffTopology/hausdorff_theory (X) 
   
   hausdorffSpace : kind = {'
		universe : type ,
		topology : hausdorffTopology universe
	'} 

theory EmptyTheory
theory EmptyTheoryWithMeta : ?EmptyTheory

view EmptyView : ?EmptyTheory -> ?EmptyTheory

theory thy =
  structure emptyStructure : ?EmptyTheory
  structure emptyStructureWithEq : ?EmptyTheory=

fixmeta blub
namespace http://github.com/ComFreek/mmtpygments/meta-annotations 

meta key "value" 
meta otherKey ?uri 

theory theory =
	meta key "value" 
	meta otherKey ?uri
	
	c: E  meta key "value"  meta otherKey ?uri 


view v: ?S -> ?T =
	meta key "value" 
	meta otherKey ?uri

	c = d meta key "value"  meta otherKey ?uri 

namespace http://github.com/ComFreek/mmtpygments 
meta ?purpose "screenshot for readme" 

theory Lists =
	list: type ⟶ type 

	nil:    {A: type} list A                 # [] %I1 prec 150 
	cons:   {A: type} A ⟶ list A ⟶ list A  # 2 :: 3 prec 100 
	append: {A: type} A ⟶ list A ⟶ list A  # 3 ;; 2 prec 80  
	
	concat: {A: type} list A ⟶ list A ⟶ list A
		 meta ?purpose "for concatenation"
		 // comment: choose a better notation?
		 # 2 ::: 3 prec 50
	


view reverse: ?Lists -> ?Lists =
	list = list 
	nil = nil 
	cons = [A, a, l] l ;; a  meta ?coolness "beyond imagination" 
	append = [A, a, l] a :: l 
	concat = ???  // missing