Convertir sans point en point

9

Étant un hacker Haskell, je préfère la notation sans point à celle avec point. Malheureusement, certaines personnes trouvent la notation sans point difficile à lire, et j'ai du mal à obtenir le nombre correct de parenthèses lorsque j'écris en pointant. Aidez-moi à convertir du code écrit en pointfree en notation pointue!

À propos de

En notation sans point, nous utilisons des points (oui, vraiment) pour alimenter la sortie d'une fonction dans une autre. Disons, si vous aviez une fonction succqui prend un nombre et y ajoute 1, et que vous vouliez créer une fonction qui ajoute 3 à un nombre, au lieu de faire ceci:

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

vous pourriez faire ceci:

succ.succ.succ

Pointfree ne fonctionne cependant qu'avec des fonctions qui prennent un seul paramètre (dans ce défi de toute façon), donc si notre fonction ne l'était pas succmais plutôt addqui prend 2 nombres et les additionne, nous devrions lui fournir des arguments jusqu'à ce qu'il n'en reste plus qu'un:

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

Enfin, les fonctions peuvent prendre d'autres fonctions comme arguments:

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))

Entrée et sortie attendue

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)))

Règles

  • Votre sortie peut avoir plus d'espaces ou de parenthèses que nécessaire, tant qu'ils sont équilibrés
  • Vous n'avez pas à vous assurer que le nom de la variable que vous créez \xn'est pas déjà utilisé ailleurs dans le code
  • A vous de choisir de créer une fonction ou un programme complet
  • C'est codegolf, le code le plus court en octets gagne!

Vous trouverez peut-être contondant utile, il convertit entre les deux notations (mais factorise également le code lorsque cela est possible): https://blunt.herokuapp.com

BlackCap
la source
15
En Pointfree notation , nous utilisons des points pour alimenter la sortie d'une fonction dans une autre C'est clairement une tentative de prouver que Pointfree n'est pas inutile
Luis Mendo
1
"Pointfree ne fonctionne qu'avec des fonctions qui prennent un seul paramètre". Ce n'est pas vrai: (+).(*3)c'est la même chose que\x y->3*x+y
Damien
2
@Damien J'essayais de rendre le défi plus accessible. Vous pouvez également faire des choses comme le hibou: (.).(.)qui se convertit en\i b c f -> i (b c f)
BlackCap
2
Donc, pour plus de clarté pour ceux qui ne connaissent pas la syntaxe de Haskell par cœur: nous devons d'abord faire correspondre les parenthèses dans l'entrée et récurrence sur chaque expression entre parenthèses de niveau supérieur; et ensuite remplacer chacun .par un (, \xajouter un et ajouter un correspondant xet autant )que nécessaire? Ou est-ce plus compliqué que ça?
Peter Taylor
1
@Linus \ d->f(\k->f(f d k)), mais vous pouvez supposer que tous les points sont alimentés par deux arguments dans ce défi
BlackCap

Réponses:

4

Haskell, 163 142 133 octets

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

Essayez-le sur Ideone.

Non 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
la source
2

Haskell, 402 289 octets

Assez longtemps, mais je pense que ça marche ..

(!)=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
la source