La sfida è scrivere un interprete per il calcolo lambda non tipizzato nel minor numero di caratteri possibile. Definiamo il calcolo lambda non tipizzato come segue:
Sintassi
Esistono tre tipi di espressioni seguenti:
Un'espressione lambda ha la forma in
(λ x. e)
cuix
potrebbe essere qualsiasi nome di variabile legale ee
qualsiasi espressione legale. Quix
si chiama il parametro ee
si chiama il corpo della funzione.Per semplicità aggiungiamo l'ulteriore limitazione che non ci deve essere una variabile con lo stesso nome
x
attualmente nell'ambito. Una variabile inizia ad essere nell'ambito quando appare il suo nome tra(λ
e.
e si ferma per essere nell'ambito nell'ambito del corrispondente)
.- L'applicazione della funzione ha la forma in
(f a)
cuif
ea
sono espressioni legali. Quif
si chiama la funzione ea
si chiama argomento. - Una variabile ha la forma in
x
cuix
è un nome di variabile legale.
Semantica
Una funzione viene applicata sostituendo ogni occorrenza del parametro nel corpo delle funzioni con il suo argomento. Più formalmente un'espressione del modulo ((λ x. e) a)
, dove x
è un nome variabile e e
e a
sono espressioni, valuta (o riduce) l'espressione in e'
cui e'
è il risultato della sostituzione di ogni occorrenza di x
in e
con a
.
Una forma normale è un'espressione che non può essere ulteriormente valutata.
La sfida
La tua missione, se scegli di accettarlo, è quella di scrivere un interprete che prenda come input un'espressione del calcolo lambda non tipizzato che non contenga variabili libere e produca come output la forma normale dell'espressione (o un'espressione alfa congruente con essa) . Se l'espressione non ha una forma normale o non è un'espressione valida, il comportamento non è definito.
Vince la soluzione con il minor numero di personaggi.
Un paio di note:
- L'input può essere letto da stdin o da un nome file indicato come argomento della riga di comando (è necessario solo implementare l'uno o l'altro, non entrambi). L'output va allo stdout.
- In alternativa è possibile definire una funzione che accetta l'input come stringa e restituisce l'output come stringa.
- Se i caratteri non ASCII sono problematici per te, puoi usare il carattere barra rovesciata (
\
) anziché λ. - Contiamo il numero di caratteri, non i byte, quindi anche se il tuo file sorgente è codificato come unicode λ conta come un carattere.
- I nomi delle variabili legali sono costituiti da una o più lettere minuscole, ovvero caratteri tra a e z (non è necessario supportare nomi alfanumerici, lettere maiuscole o lettere non latine, sebbene ciò non invalidi la soluzione, ovviamente).
- Per quanto riguarda questa sfida, nessuna parentesi è facoltativa. Ogni espressione lambda e ogni applicazione di funzione saranno circondate esattamente da una coppia di parentesi. Nessun nome di variabile sarà racchiuso tra parentesi.
- Lo zucchero sintattico come la scrittura
(λ x y. e)
per(λ x. (λ y. e))
non ha bisogno di essere supportato. - Se per valutare una funzione è necessaria una profondità di ricorsione superiore a 100, il comportamento non è definito. Dovrebbe essere abbastanza basso da essere implementato senza ottimizzazione in tutte le lingue e comunque abbastanza grande da essere in grado di eseguire la maggior parte delle espressioni.
- Si può anche supporre che la spaziatura sia come negli esempi, cioè senza spazi all'inizio e alla fine dell'input o prima di uno
λ
o.
esattamente uno spazio dopo una.
e tra una funzione e il suo argomento e dopo unaλ
.
Ingresso e uscita campione
Ingresso:
((λ x. x) (λ y. (λ z. z)))
Produzione:
(λ y. (λ z. z))
Ingresso:
(λ x. ((λ y. y) x))
Produzione:
(λ x. x)
Ingresso:
((λ x. (λ y. x)) (λ a. a))
Produzione:
(λ y. (λ a. a))
Ingresso:
(((λ x. (λ y. x)) (λ a. a)) (λ b. b))
Produzione:
(λ a. a)
Ingresso:
((λ x. (λ y. y)) (λ a. a))
Produzione:
(λ y. y)
Ingresso:
(((λ x. (λ y. y)) (λ a. a)) (λ b. b))
Produzione:
(λ b. b)
Ingresso:
((λx. (x x)) (λx. (x x)))
Output: nulla (Questo è un esempio di un'espressione che non ha forma normale)
Ingresso:
(((λ x. (λ y. x)) (λ a. a)) ((λx. (x x)) (λx. (x x))))
Output:
(λ a. a)
(Questo è un esempio di un'espressione che non si normalizza se si valutano gli argomenti prima della chiamata della funzione, e purtroppo un esempio per il quale la mia tentata soluzione fallisce)Ingresso:
((λ a. (λ b. (a (a (a b))))) (λ c. (λ d. (c (c d)))))
Output:
`(λ a. (λ b. (a (a (a (a (a (a (a (a b))))))))))
calcola 2 ^ 3 in cifre della Chiesa.
(\y. a)
.