SKR

From Esolang
Jump to navigation Jump to search
SKR
Paradigm(s) Functional
Designed by User:Hakerh400
Appeared in 2024
Computational class Turing complete
Major implementations Implemented
File extension(s) .txt

SKR is an esolang invented by User:Hakerh400 in 2024.

Overview

SKR is a purely functional Turing tarpit based on combinatory logic. There are 3 combinators: K, S, R, and the following rewriting rules:

K x y     ---> x
S x y z   ---> x z (y z)
R x K     ---> x K
R x S     ---> x K
R x R     ---> x K
R x (y z) ---> x S y z

In the last rule, the expression y z must be a WHNF (weak head normal form). A WHNF is one of: K, K x, R, R x, S, S x, S x y, for any expressions x and y (x and y do not need to be WHNFs).

Syntax

Source code consists of definitions. A definition starts with an identifier, then equals sign =, and finally the expression. The last definition in the source code represents the main function. It is called with the input as argument and the result is the output. Definition cannot reference itself, only the definitions before it.

Expression syntax supports the # operator. It represents the low-precedence right-associative application operator. For example, a # b # c d is a (b (c d)).

Features

The unique feature that this language provides is the ability to fully introspect expressions in the language itself. Unlike in the standard SKI calculus, SKR provides a mechanism to analyze expressions without evaluating them.

Examples

Some useful functions:

I = S K K
B = S (K S) K
BB = B B
C = S (BB S) # K K
BC = B C
W = C S I
T = K
F = K I
app_fst = R # K T
app_snd = R # K F
fst = B app_snd app_fst
snd = app_snd
B2 = BB B
B3 = BB B2
B4 = BB B3
B5 = BB B4
B2' = B BC # B2 BB B
B2x = B3 W B2'
CI = C I
CI2 = BC CI
CI3 = B2 C CI2
W3' = C (B S W) I
I2 = W I
I3 = W3' I
K2 = B K K
K3 = B K K2
C2 = BC BC
C3 = BC # B C2
C4 = BC # B C3
C5 = BC # B C4
C2' = B2 C C
C3' = B2 C2' C
C4' = B2 C3' C
C5' = B2 C4' C
S2 = I2 # B S
W2 = B2 W # B W BC
Bhfxy = B W # B2 C # B (B2 B) B
Bhfxyzr = B W # B2 C2 # B2 (B2 B2) B2
pair_cs = C (B S # C B fst) snd
pair_rd = B3 pair_cs B2'
swap = pair_cs # C S
not = C (CI F) T
or = CI T
and = C C F
iff = C S not
xor = B2 not iff
xor3 = W B2 xor
or_and = C2 (B2 B2 # B2 or and) and
or_and3 = C4 (B4 B2 # B4 or or_and) and
at_least_2 = B2 W # B W # B2 C # W # BC or_and3
is_K_or_R' = CI3 I F K
is_S' = B not is_K_or_R'
is_K_aux = C2' (W3' S) K I
is_R_aux = B not is_K_aux
and' = B2x and
is_KR_aux = and' is_K_or_R'
is_K' = is_KR_aux is_K_aux
is_R' = is_KR_aux is_R_aux
is_comb = R # C (C is_K' T) # K2 F
is_app = B not is_comb
and_safe = C2 (B2 S # C2 C2' # K F) I
andf = W # BC # B2 B # B and
is_comb_aux = and_safe is_comb
is_K = is_comb_aux is_K'
is_S = is_comb_aux is_S'
is_R = is_comb_aux is_R'
cs_comb = C (B B2 # B S # C is_K) # C2' is_S
cs_app = B R K
cs_aux1 = B3 K cs_comb
cs_aux2 = K3 cs_app
cs = C4 (B4 S # C4' # C2' is_comb cs_aux1 cs_aux2) I
cs3 = W3' cs
rec_app = B2 cs_app # S (BC # B BC # B2 (B S) # C # B S BC) I
rec_aux1 = K # B3 K cs_comb
rec_aux2 = C4 (B4 S # B4 (B rec_app) I2) I
rec_r = C5 (B5 S # C5' # C2' is_comb rec_aux1 rec_aux2) I
rec = I2 rec_r
rec3 = W3' rec
eq = rec is_K is_S is_R # K2 # B2 (cs3 F) # B2' and
ne = B2 not eq
cs2_fn' = B2 C # B (S I # B C2) B2
cs2_fn = C (B B cs2_fn') BC
pair_cs2 = cs2_fn pair_cs
mk_fn' = BC # B2 I2 # B2 (B2 W) # C (B B # C C4' # K K) # C # B B2 I2
mk_fn = mk_fn' is_R
nat_b0 = S (C is_K K) # S K
nat_b1 = S S
nat_b = C2' I nat_b1 nat_b0
0 = K
1 = nat_b1 0
nat_cs_aux = B (C2' is_K) # B K # C2' I F 0
nat_cs = B W # S nat_cs_aux # B pair_cs # C B is_S
nat_csz = B2 W # C (B (C3' is_K) K2) nat_cs
nat_cs2 = cs2_fn nat_cs
nat_op_c_nz_aux1 = B # S # B S2 # B (B2 B2) # B (B2 nat_b) xor3
nat_op_c_nz_aux2 = B nat_op_c_nz_aux1 # C # B B # B B2 I2
nat_op_c_nz = B (B2 nat_cs2) nat_op_c_nz_aux2
nat_op_c_aux = C4' (B C4' # andf is_K) # K # B K2 # C2' I 1 0
nat_op_c = B I2 # B (B2 W2) # B nat_op_c_aux nat_op_c_nz
nat_op = C nat_op_c F
nat_add = nat_op at_least_2
nat_succ = nat_add 1
nat_subt' = nat_op # C3' I and or
nat_le = B (S eq) # S (B B nat_add) # C nat_subt'
nat_lt = S2 (B2 and nat_le) # B2 not eq
nat_ge = C nat_le
nat_gt = C nat_lt
nat_subt = W2 # C2 (C2 nat_ge nat_subt') # K2 0
2 = nat_succ 1; 3 = nat_succ 2; 4 = nat_succ 3
5 = nat_succ 4; 6 = nat_succ 5; 7 = nat_succ 6
8 = nat_succ 7; 9 = nat_succ 8; 10 = nat_succ 9
nat_mul_nz_aux = B # S # BC # B2 B # C (B (C2' I) nat_add) I
nat_mul_nz = B2 nat_cs # nat_mul_nz_aux # C (B B I2) nat_b0
nat_mul = I2 # B2 W # C4' is_K (K3 0) nat_mul_nz
nat_snoc = B nat_add # nat_mul 10
nat = mk_fn 0 nat_snoc
nat_min = W2 nat_le
nat_max = W2 nat_ge
int_aux = C2' # B (Bhfxy S) # C nat_subt
int' = S2 int_aux nat_min
int_op = B pair_cs2 # Bhfxyzr int'
int_add = int_op nat_add
int_neg = swap
int_sub = C (B B int_add) int_neg
nat_to_int = C int' 0
int0 = nat_to_int 0
int_snoc = C # B pair_cs # B2 S # C nat_snoc
int = mk_fn int0 int_snoc
int_mul_aux1 = Bhfxyzr nat_add nat_mul
int_mul_aux2 = S2 # B2 S2 # B2 (B2 int') int_mul_aux1
int_mul = pair_cs2 # int_mul_aux2 # B C2 int_mul_aux1
nat_inc = nat_succ
nat_dec = C nat_subt 1
nat_rec_nz = B2 (S2 I) I2
nat_rec_aux = C3 (B3 B nat_rec_nz) nat_dec
nat_rec = I2 # B3 W # C5' is_K (K K2) nat_rec_aux
nat_iter = C (B B nat_rec) K
nat_pow = B (nat_iter 1) nat_mul
cnt' = C (S (S (B rec # CI K) # CI S) # CI R) # K2 nat_add
cnt = B cnt' # C2' C2' 1 0
list_rec_nz = B2 (B pair_cs) # B2 (S # BC # B S) I2
list_rec = I2 # B3 W # C5' is_K (K K2) list_rec_nz
foldr = C (B B list_rec) # B K
nat_sum = foldr 0 nat_add
nat_prod = foldr 1 nat_mul
foldl = C (B B2 CI) # B (C # C # foldr I) # B2 (C B) C
sngl = C S K
snoc = C2' (B foldr sngl) S
list' = C2' mk_fn' K snoc
list = list' is_R
reverse = foldl K # C S
append = C2' foldr S

As an example, we can use the above functions to check which combinator appears most frequently in the input:

fn' = B S # B2 S # S (B C # B2 B nat_ge) # C2' (B C2' nat_ge) K R
fn = C fn' # C2' (B C2' nat_ge) S R
main = B (S (S (B fn # CI is_K) # CI is_S) # CI is_R) # C cnt

This program outputs the combinator that appears the maximum number of times in the input. If the input is S (S (R # K R) # S R # S S) # R # K # K # K # K # R R, the output will be R. Note that the combinator count is examined in the context of fully evaluated input expression.

Implementation