Converter pointfree em pointful

9

Sendo um hacker Haskell, prefiro notação sem ponto a ponto. Infelizmente, algumas pessoas acham difícil ler a notação sem ponto, e acho difícil obter o número correto de parênteses quando escrevo em questão. Ajude-me a converter o código escrito em notação sem ponto para notação significativa!

Sobre

Na notação sem ponto, usamos pontos (sim, realmente) para alimentar a saída de uma função em outra. Digamos, se você tivesse uma função succque pega um número e adiciona 1 a ele, e desejava criar uma função que adiciona 3 a um número, em vez de fazer isso:

\x -> succ(succ(succ(x)))

você poderia fazer isso:

succ.succ.succ

No entanto, o Pointfree funciona apenas com funções que usam um único parâmetro (nesse desafio, de qualquer forma); portanto, se nossa função não fosse, succmas addque pegasse 2 números e os adicionasse, teríamos que alimentar argumentos até restar apenas um:

pointful:  \x -> add 1(add 1(add 1 x)) 
pointfree: add 1 . add 1 . add 1

Por fim, funções podem assumir outras funções como argumentos:

Pointfree: map (f a . f b) . id
Pointful:  \x -> map (\x -> f a (f b x)) (id x)

Javascript equivalent: x => map (x => f(a,f(b,x)), id(x))

Entrada e saída esperada

f . f . f
\x -> f (f (f x))

f a . f b . f c
\x -> f a (f b (f c x))

f (f a . f b) . f c
\x -> f (\x -> f a (f b x)) (f c x)

a b c . d e . f g h i . j k l . m
\x -> a b c (d e (f g h i (j k l (m x))))

a.b(c.d)e.f g(h)(i j.k).l(m(n.o).p)
\x->a(b(\y->c(d y))e(f g h(\z->i j(k z))(l(\q->m(\w->n(o w))(p q))x)))

Regras

  • Sua saída pode ter mais espaços ou parênteses do que o necessário, desde que equilibrados
  • Você não precisa se certificar de que o nome da variável que você cria \xainda não esteja sendo usado em outro lugar no código
  • É sua escolha criar uma função ou um programa completo
  • Isto é codegolf, o código mais curto em bytes ganha!

Você pode achar útil, mas ele converte entre as duas notações (mas também fatora o código quando possível): https://blunt.herokuapp.com

BlackCap
fonte
15
Em pointfree notação que usamos pontos para alimentar a saída de uma função para outra Isso é claramente uma tentativa de provar que pointfree não é inútil
Luis Mendo
11
"O Pointfree funciona apenas com funções que usam um único parâmetro". Isso não é verdade: (+).(*3)é o mesmo que\x y->3*x+y
Damien
2
@ Damien Eu estava tentando tornar o desafio mais acessível. Você também pode fazer coisas como a coruja: (.).(.)que se converte em\i b c f -> i (b c f)
BlackCap 29/09/16
2
Portanto, para maior clareza para quem não conhece a sintaxe de Haskell de cor: devemos primeiro corresponder parênteses na entrada e repetir cada expressão entre parênteses de nível superior; e substitua cada .um por um (, \xacrescente um a e anexe um correspondente xe quantos )forem necessários? Ou é mais complicado que isso?
Peter Taylor
11
@Linus \ d->f(\k->f(f d k)), mas você pode assumir que todos os pontos são alimentados dois argumentos neste desafio
Cabeção

Respostas:

4

Haskell, 163 142 133 bytes

p(x:r)|[a,b]<-p r=case[x]of"("->["(\\x->"++a++p b!!0,""];"."->['(':a++")",b];")"->[" x)",r];_->[x:a,b]
p r=[r,r]
f s=p('(':s++")")!!0

Experimente em Ideone.

Ungolfed:

p('(':r)|(a,b)<-p r = ("(\\x->"++a++(fst(p b)),"")
p('.':r)|(a,b)<-p r = ('(':a++")",              b)
p(')':r)            = (" x)",                   r)
p(x  :r)|(a,b)<-p r = (x:a,                     b)
p _                 = ("",                     "")

f s=fst(p('(':s++")"))
Laikoni
fonte
2

Haskell, 402 289 bytes

Muito tempo, mas acho que funciona ..

(!)=elem
n%'('=n+1
n%')'=n-1
n%_=n
a?n=a!"."&&n<1
a#n=a!" ("&&n<1||a!")"&&n<2
q a='(':a++")"
p s o n[]=[s]
p s o n(a:b)|o a n=[t|t@(q:r)<-s:p""o(n%a)b]|0<1=p(s++[a])o(n%a)b
k=foldr((++).(++" ").f)"".p""(#)0
f t|not$any(!"(. ")t=t|l@(x:r)<-p""(?)0t=q$"\\x->"++foldr((.q).(++).k)"x"l|0<1=k t
Damien
fonte