Scott numeral

From Esolang
Jump to navigation Jump to search

A Scott numeral is a natural number encoded into lambda calculus using Mogensen–Scott encoding. In contrast to the better-known Church numerals, Scott numerals have a different performance profile and can be a better choice for certain applications.

Definition

Scott numerals have the following wikipedia:System F type signature:

ΛX. (ΛR. (X → R) → (R → R)) → (X → X)

Intuitively, Scott encoding provides one input argument per constructor of the equivalent data type. This signature is the encoding of the recursive type:

data Nat = Succ Nat | Zero

If the numeral is a zero, then it can return the identity function; otherwise, it can pass another Scott numeral to the successor function. The caller chooses the type X where the zeros and other concrete natural numbers are interpreted; the numeral chooses the type R where the successor operation is performed, including the common choice R = X for purely numeric behavior.

Examples

numbers

0 = λs.λz.z
1 = λs.λz.s 0 = λs.λz.s (λs.λz.z)
2 = λs.λz.s 1 = λs.λz.s (λs.λz.s (λs.λz.z))

successor function and predecessor function

succ = λn.λs.λz.s n
pred = λn.n (λx.x) 0

Arithmetic

First,we need a fixed point combinator

fix = (λx.x x)(λf.λx.x(f f x))

additive function

add = fix (λf.λx.λy.y (λn.succ (f x n)) x)

subtraction function

sub = fix (λf.λx.λy.y (λn.pred (f x n)) x)

multiplication function

mul = fix (λf.λx.λy.y (λn.add x (f x n)) 0)

division function

div = fix (λf.λx.λy.(succ (sub x y)) (λn.succ (f (sub x y) y)) 0)

Predicate

First,we need boolean.

true = λt.λf.t
false = λt.λf.f

test if a number is zero

isZero = λn.n (λx.false) true

test if a number is less than or equal to another number

leq = λx.λy.isZero (sub x y)

test if a number is equal to another number

eq = λx.λy.(leq x y) (leq y x) false

test if a number is less than another number

lt = λx.λy.(eq x y) false (leq x y)

test if a number is even

even = λn.isZero (sub n (mul 2 (div n 2)))

Convert between Church numeral

First,we need church succ and church pred.

cSucc = λn.λs.λz.s(n s z)
cPred = λn.(n (λp.λx.x (p false) (succ (p false))) (λx.x 0 0)) true

convert to church numeral

toChurch = fix (λf.λx.x (λn.cSucc (f n)) (λs.λz.z))

convert from church numeral

fromChurch = λn.n succ 0