====== ABORDAGEM UM (sinal,magnitude) =======

NUMERO INTEIRO = pair boolean natural
  - boolean :  true = positivo,  false = negativo
  - natural :  magnitude


...
neg_dois = pair false 2;
neg_um   = pair false 1;
neg_zero = pair false 0;
pos_zero = pair true  0;
pos_um =   pair true  1;
pos_dois = pair true  2;
...


;; teste de sinal, basicamente extrair o primeiro campo do par ordenado
int_isZero = \m. isZero (snd m);
int_isPos  = \m. (and (not (int_isZero m)) (fst m));
int_isNeg  = \m. (and (not (int_isZero m)) (not (fst m)));

;; -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
;; 2012 08 17 02 55
;; Sugestao:
;; int_isPos = \m. ((fst m)and(not(isZero m)));
;; int_isNeg = \m. ((not(fst m))and(not(isZero m)));
;; pois isPos nao deveria responder true para pair true 0
;; pois isNeg nao deveria responder true para pair false 0
;; afinal, +0 e -0 nao eh nem positivo, nem negativo; eh nulo
;; (acho que a sintaxe nao estah certa)
;; 
;; verdade, os termos estavam errados! 
;; corrigi acima, botei na sintaxe do interpretador e testei
;; obrigado!!!
;; -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

;; testa se sinais são iguais: se forem, mantém sinal e faz uma soma. 
;;                             se não forem, testa a magnitude e faz uma subtração, mantendo o sinal
;;                                da maior magnitude
int_soma = \m. \n. if (sss (fst m) (fst n))   
                      (pair (fst m) (add (snd m) (snd n)))
                      (if (great (snd m) (snd n))
                          (pair (fst m) (sub (snd m) (snd n)))
                          (pair (fst n) (sub (snd n) (snd m))));



====== ABORDAGEM DOIS ( fffx ou ggggggx, dois argumentos f e g, um representando +1, o outro representando -1)

...
neg_dois = \f.\g.\x. g (g x);
neg_um   = \f.\g.\x. g x;
zero     = \f.\g.\x. x;
pos_um   = \f.\g.\x. f x;
pos_dois = \f.\g.\x. f (f x);
...

;;; teste de sinal
int_isZero = \m. m (\x.false) (\x.false)  true;
int_isPos  = \m. m (\x.true)  (\x.false)  false;
int_isNeg  = \m. m (\x.true)  (\x.false)  false;

;;; predecessor dos naturais, necessário como função auxiliar
zero     = \f. \x. x ;
shiftInc = (\p.(pair (snd p) (succ (snd p))));
pred     = \n. fst (n shiftInc (pair zero zero)) ;

;;; soma um a inteiro
int_succ   = \m. if (not (int_isNeg m))
                    (\f.\g.\x. f (m f g x))
                    (\f.\g.\x. (fst (m f shiftInc (pair zero zero))) g x);

;;; subtrai um de inteiro
int_pred   = \m. if (not (int_isPos m))
                    (\f.\g.\x. g (m f g x))
                    (\f.\g.\x. (fst (m shiftInc g (pair zero zero))) f x);

;;; inverso do número
int_inv    = \m.\f.\g.\x. m g f x;

;;; valor absoluto
int_abs    = \m.\f.\g.\x. m f f x;
                    
;;; conversão do valor absoluto inteiro para naturais de church
int_to_nat = \m.\f.\x. m f f x;

;;; adição inteira
int_add    = \m. \n. m int_succ int_pred n;

;;; subtração inteira
int_sub    = \m. \n. int_add m (int_inv n);

;;; comparações
int_equal =  \m. \n. int_isZero (int_sub m n);
int_less  =  \m. \n. int_isNeg  (int_sub m n);
int_lessEq = \m. \n. or (int_equal m n) (int_less m n);
int_great =  \m. \n. not (int_lessEq m n);
int_gretEq = \m. \n. not (int_less m n);



Acho que com esses ingredientes básicos definidos, o resto da aritmética inteira é tranquila...


======== SITES LEGAIS SOBRE LAMBDA CALCULUS

http://okmij.org/ftp/Computation/lambda-calc.html


