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)