Convierta punto libre a significativo

9

Siendo un hacker de Haskell, prefiero la notación de punto libre en lugar de significativa. Desafortunadamente, algunas personas encuentran que la notación de punto libre es difícil de leer, y me resulta difícil obtener el número correcto de paréntesis cuando escribo en punto. ¡Ayúdame a convertir el código escrito en punto libre a notación significativa!

Acerca de

En notación sin puntos, usamos puntos (sí, realmente) para alimentar la salida de una función a otra. Digamos, si tenía una función succque toma un número y le agrega 1, y desea hacer una función que agregue 3 a un número, en lugar de hacer esto:

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

podrías hacer esto:

succ.succ.succ

Sin embargo, Pointfree solo funciona con funciones que toman un solo parámetro (en este desafío de todos modos), por lo que si nuestra función no fuera succmás addque tomar 2 números y agregarlos, tendríamos que alimentar sus argumentos hasta que solo quede uno:

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

Por último, las funciones pueden tomar otras funciones 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 y salida 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)))

Reglas

  • Su salida puede tener más espacios o paréntesis de los necesarios, siempre que estén equilibrados
  • No tiene que asegurarse de que el nombre de la variable que cree \xya no se use en otro lugar del código
  • Es su elección si crear una función o un programa completo
  • Esto es codegolf, ¡el código más corto en bytes gana!

Es posible que encuentre contundente útil, convierte entre las dos notaciones (pero también factoriza el código cuando sea posible): https://blunt.herokuapp.com

Alondra
fuente
15
En la notación sin puntos, utilizamos puntos para alimentar la salida de una función a otra. Eso es claramente un intento de demostrar que no tiene sentido
Luis Mendo
1
"Pointfree solo funciona con funciones que toman un solo parámetro". Eso no es cierto: (+).(*3)es lo mismo que\x y->3*x+y
Damien
2
@Damien Estaba tratando de hacer el desafío más accesible. También puede hacer cosas como el búho: (.).(.)que se convierte a\i b c f -> i (b c f)
BlackCap
2
Entonces, para mayor claridad para aquellos que no conocen la sintaxis de Haskell de memoria: primero debemos hacer coincidir los paréntesis en la entrada y recurrir en cada expresión de paréntesis de nivel superior; y luego reemplace cada uno .con a (, anteponga a \xy agregue un correspondiente xy tantos )como sea necesario? ¿O es más complicado que eso?
Peter Taylor
1
@Linus \ d->f(\k->f(f d k)), pero puedes suponer que todos los puntos se alimentan de dos argumentos en este desafío
BlackCap el

Respuestas:

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

Pruébalo en Ideone.

Sin golf:

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
fuente
2

Haskell, 402 289 bytes

Bastante largo, pero creo 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
fuente