; Y-combinator for descartes Lisp/ λ

;; Y-combinator

(define Y 
  λfλp (f λa ((p p) a))
     λp (f λa ((p p) a)))


;; factorial
(define fact 
  λfλn 
        (cond 
          ((<= n 1) 1) 
           (T (* n (f (- n 1))))))

((Y fact) 5) 

;; Factorial by λ type 1
(((λ (f) ((λ (p) (f (λ (a) ((p p) a)))) (λ (p) (f (λ (a) ((p p) a))))))
  (λ (f) (λ (n) (cond ((<= n 1) 1) (T (* n (f (- n 1))))))))
  6)

;; Factorial by λ type 2
((λ (n) (cond ((<= n 1) 1) (T (* n ((λ (n) (cond ((<= n 1) 1) (T (* n ((λ (a)
(((λ (p) ((λ (f) (λ (n) (cond ((<= n 1) 1) (T (* n (f (- n 1))))))) (p p) a))
 (λ (p) ((λ (f) (λ (n) (cond ((<= n 1) 1) (T (* n (f (- n 1))))))) (p p) a)))
 a)) (- n 1)))))) (- n 1))))))
7)

;; list length

(define length
  λfλl
        (cond 
          ((equal l ()) 0) 
          ((atom l) 1)
          (T (+ (f (cdr l)) 1))))

((Y length) '(a b c)) 

;; length by λ type1
(((λ (f) (f ((λ (p) (f (λ (a) ((p p) a)))) (λ (p) (f (λ (a) ((p p) a))))) a))
 (λ (f) (λ (l) (cond ((equal l ()) 0) ((atom l) 1) (T (+ (f (cdr l)) 1))))))
 '(1 2 3 4 5 6 7))

;; length by λ type2
((λ (l) (cond ((equal l ()) 0) ((atom l) 1) (T (+ ((λ (l) (cond ((equal l ()) 0) ((atom l) 1) (T (+ ((λ (a) (((λ (p) ((λ (f) (λ (l) (cond ((equal l ()) 0) ((atom l) 1) (T (+ (f (cdr l)) 1))))) (p p) a)) (λ (p) ((λ (f) (λ (l) (cond ((equal l ()) 0) ((atom l) 1) (T (+ (f (cdr l)) 1))))) (p p) a))) a)) (cdr l)) 1)))) (cdr l)) 1))))
 '(1 2 3 4 5 6 7))

;; Fibonacci number

(define fib
  λfλn 
        (cond 
          ((= n 0) 0) 
          ((= n 1) 1) 
          (T (+ (f (- n 1)) (f (- n 2))))))


((Y fib) 3)

;; Fibonacci by λ type1
(((λ (f) (f ((λ (p) (f (λ (a) ((p p) a)))) (λ (p) (f (λ (a) ((p p) a))))) a))
  (λ (f) (λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ (f (- n 1)) (f (- n 2))))))))
  4)

;; Fibonacci by λ type2
((λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ ((λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ ((λ (a) (((λ (p) ((λ (f) (λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ (f (- n 1)) (f (- n 2))))))) (p p) a)) (λ (p) ((λ (f) (λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ (f (- n 1)) (f (- n 2))))))) (p p) a))) a)) (- n 1)) ((λ (a) (((λ (p) ((λ (f) (λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ (f (- n 1)) (f (- n 2))))))) (p p) a)) (λ (p) ((λ (f) (λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ (f (- n 1)) (f (- n 2))))))) (p p) a))) a)) (- n 2)))))) (- n 1)) ((λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ ((λ (a) (((λ (p) ((λ (f) (λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ (f (- n 1)) (f (- n 2))))))) (p p) a)) (λ (p) ((λ (f) (λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ (f (- n 1)) (f (- n 2))))))) (p p) a))) a)) (- n 1)) ((λ (a) (((λ (p) ((λ (f) (λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ (f (- n 1)) (f (- n 2))))))) (p p) a)) (λ (p) ((λ (f) (λ (n) (cond ((= n 0) 0) ((= n 1) 1) (T (+ (f (- n 1)) (f (- n 2))))))) (p p) a))) a)) (- n 2)))))) (- n 2))))))
  5)


