Classifique uma lista de números no cálculo λ


8

Escreva um termo no cálculo lambda puro não digitado que, quando aplicado a uma lista de números codificados por igrejas , o retorne com seus números classificados em ordem crescente ou decrescente. As listas e os números das igrejas devem ser codificados como dobras para seus ADTs habituais:

-- Usual ADTs for Lists and Nats (in Haskell, for example)
data List a = Cons a (List a) | Nil
data Nat a  = Succ (Nat a) | Zero

-- Their respective folds are the λ-calculus representation used on this challenge
church_list = (λ c n . (c ... (c ... (c ... n))))
church_num  = (λ succ zero . (succ (succ (succ ... zero))))

Exemplo de entrada:

(λ cons nil .
    (cons (λ f x . (f x))                         -- 1
    (cons (λ f x . (f (f (f (f (f (f (f x)))))))) -- 7
    (cons (λ f x . (f (f x)))                     -- 2
    (cons (λ f x . (f (f (f x))))                 -- 3
    nil)))))

Exemplo de saída:

(λ cons nil . 
    (cons (λ f x . (f x))                         -- 1
    (cons (λ f x . (f (f x)))                     -- 2
    (cons (λ f x . (f (f (f x))))                 -- 3
    (cons (λ f x . (f (f (f (f (f (f (f x)))))))) -- 7
    nil)))))

A pontuação de uma submissão será calculada da seguinte forma:

score(x)    = 1
score(λx.t) = score(t) + 1
score(t s)  = score(t) + score(s) + 1

Menor pontuação ganha.


7
A página vinculada fornece três codificações diferentes da Igreja para listas, e não há nada para impedir que isso mude no futuro. Para que a pergunta seja inequívoca, você precisará definir explicitamente a codificação específica que tem em mente na pergunta. (Também seria aconselhável definir a codificação dos números).
Peter Taylor

1
ordem crescente ou decrescente - por que escolhemos?
21415 Lynn

Só não encontrei um motivo para limitá-lo. Por que não?
MaiaVictor

Respostas:


3

Consegui superar minha própria marca:

sort = λabcd.a(λef.f(λghi.g(λj.h(λkl.kj(ikl)))(hi))e(λgh.h))
       (λe.d)(λe.b(λf.e(f(λghi.hg)(λgh.cfh))))

Porém, existe uma ressalva - esse termo deve receber um argumento adicional com o tamanho máximo de naturais considerado. Por exemplo, sort 4 [1,7,3,6,5]retornará [1,3], ignorando qualquer coisa acima ou igual a 4. É claro, você poderia apenas fornecer infinito (ou seja, o combinador Y):

sort = λbcd.(λfx.f(x x))(λfx.f(x x))(λef.f(λghi.g(λj.h(λkl.kj(ikl)))
       (hi))e(λgh.h))(λe.d)(λe.b(λf.e(f(λghi.hg)(λgh.cfh))))

E classificaria qualquer lista de números naturais, mas esse termo obviamente não tem mais uma forma normal.


1

121 caracteres / pontuação 91

sort = λabc.a(λdefg.f(d(λhij.j(λkl.k(λmn.mhi)l)(h(λkl.l)i))
       (λhi.i(λjk.bd(jhk))(bd(h(λjk.j(λlm.m)k)c))))e)(λde.e)
       (λde.d(λfg.g)e)c

Está na forma normal e pode ser reduzido, levantando subexpressões comuns.


1

Aqui está uma implementação de um tipo de inserção:

let nil =       \f x.x in
let cons = \h t.\f x.f h (t f x) in
let 0 =       \f x.x in
let succ = \n.\f x.f (n f x) in
let None =    \a b.b in
let Some = \x.\a b.a x in
let pred = \n.n (\opt.opt (\m.Some(succ m)) (Some 0)) None in
let optpred = \opt.opt pred None in
let - = \m n.n optpred (Some m) in
let < = \m n.\trueval falseval.- m n (\diff.falseval) trueval in
let pair = \x y.\f.f x y in
let snd = \p.p (\x y.y) in
let insert = \n l.snd (l (\h recpair.recpair (\rawtail insertedtail.
  let rawlist = cons h rawtail in
    pair rawlist (< h n (cons h insertedtail) (cons n rawlist))))
  (pair nil (cons n nil))) in
\l.l insert nil

Aqui, pred nretorna um elemento de option nat: pred 0is Noneenquanto pred (n+1)é Some n. Então, - m nretorna um elemento do option natqual é Some (m-n)se m>=nou Nonese m<n; e < m nretorna um booleano. Finalmente, insertusa uma função interna retornando um par where f l = (l, insert n l)(um método bastante típico para passar a cauda da lista para a recursão junto com o valor recursivo).

Agora, algumas notas para o futuro trabalho de golfe: Na verdade nil, 0, Noneacontecerá a ser a mesma função formalmente (e ele também aparece em snd). Então, eu certamente consideraria fazer reduções beta nas letdeclarações (que é, obviamente, o açúcar sintático usual onde let a = x in ysignifica (\a.y)xe, portanto, tem pontuação score(x) + score(y) + 2) para ver em quais casos isso reduziria a pontuação - o que definitivamente seria para as ligações que são usado apenas uma vez.

Em seguida, viria coisas mais complicadas: por exemplo, eu só notei que formalmente pred = pair (pair (\m.Some(succ m)) (Some 0)) None, optpred = pair pred None, - = \m.pair optpred (Some m), a definição da função tipo equivale a pair insert nil, etc., que poderia reduzir o marcador ligeiramente.


Calcule sua pontuação e indique-a na resposta #
Nathaniel
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.