(define nat->number
  (lambda (ls)
    (if (nzero? ls)
	0
	(+ 1 (nat->number (nsub1 ls))))))

(define number->nat
  (lambda (x)
    (if (= x 0)
	n0
	(nadd1 (number->nat (- x 1))))))

(define n0 '())

(define nadd1
  (lambda (x)
    (cons x '())))

(define n1 (nadd1 n0))

(define nsub1 car)

(define nzero? null?)

;; x+0 = x
;; x+y = [x + (y-1)] + 1
(define n+
  (lambda (x y)
    (if (nzero? y)
	x
	(nadd1 (n+ x (nsub1 y))))))

;; x-0 = x
;; x-y = [x - (y-1)] - 1
(define n-
  (lambda (x y)
    (if (nzero? y)
	x
	(nsub1 (n- x (nsub1 y))))))

;; x*0 = 0
;; x*y = [x*(y-1)] + x
(define n*
  (lambda (x y)
    (if (nzero? y)
	n0
	(n+ x (n* x (nsub1 y))))))

;; x^0 = 1
;; x^y = x * x^(y-1)
(define n^
  (lambda (x y)
    (if (nzero? y)
	n1
	(n* x (n^ x (nsub1 y))))))

;; 0! = 1
;; x! = x * (x-1)!
(define n!
  (lambda (x)
    (if (nzero? x)
	n1
	(n* x (n! (nsub1 x))))))

;; WARNING: Here are alternative definitions of nadd1 and nsub1. 
;; Feel free to try them out. But be careful of brain aches! :)

(define n0 ())

(define nzero? null?)

(define nadd1
  (lambda (x)
    (lambda () x)))

(define nsub1
  (lambda (x) (x)))