Konwertuj pointfree na pointful

9

Będąc hakerem Haskell, wolę notację punktową niż punktową. Niestety niektórym osobom trudno jest odczytać bezcelową notację i trudno mi uzyskać prawidłową liczbę nawiasów, gdy piszę w sposób celny. Pomóż mi przekonwertować kod napisany w pointfree na notację punktową!

O

W notacji wolnej od punktów używamy punktów (tak, naprawdę), aby wprowadzić dane wyjściowe jednej funkcji do drugiej. Powiedzmy, że jeśli masz funkcję, succktóra pobiera liczbę i dodaje do niej 1, a chcesz zrobić funkcję, która dodaje 3 do liczby, zamiast tego:

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

możesz to zrobić:

succ.succ.succ

Pointfree działa tylko z funkcjami, które pobierają tylko jeden parametr (w każdym razie w tym wyzwaniu), więc jeśli nasza funkcja nie była, succale raczej, addktóra bierze 2 liczby i dodaje je razem, musielibyśmy podawać argumenty, dopóki nie zostanie tylko jeden:

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

Wreszcie funkcje mogą przyjmować inne funkcje jako argumenty:

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

Dane wejściowe i oczekiwane wyniki

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

Zasady

  • Dane wyjściowe mogą zawierać więcej spacji lub nawiasów niż jest to wymagane, o ile są zrównoważone
  • Nie musisz się upewnić, że nazwa tworzonej zmiennej nie \xjest już używana gdzie indziej w kodzie
  • Od Ciebie zależy, czy chcesz utworzyć funkcję, czy pełny program
  • To jest codegolf, najkrótszy kod w bajtach wygrywa!

Może się okazać, że tępy jest użyteczny, konwertuje między dwoma notacjami (ale także rozkłada kod, jeśli to możliwe): https://blunt.herokuapp.com

Gajówka
źródło
15
W notacji bez punktowej używamy punktów do wprowadzania danych wyjściowych jednej funkcji do drugiej. Jest to wyraźnie próba udowodnienia, że ​​bezcelowa nie jest bezcelowa
Luis Mendo,
1
„Pointfree działa tylko z funkcjami, które wymagają jednego parametru”. To nieprawda: (+).(*3)to to samo co\x y->3*x+y
Damien
2
@Damien Próbowałem uczynić wyzwanie bardziej dostępnym. Możesz także robić takie rzeczy jak sowa: (.).(.)która zamienia się w\i b c f -> i (b c f)
BlackCap
2
Dla jasności dla tych, którzy nie znają składni Haskell na pamięć: powinniśmy najpierw dopasować nawiasy w danych wejściowych i powtórzyć każde wyrażenie w nawiasie najwyższego poziomu; a następnie zamień każdy na .a (, \xdodaj a i dodaj odpowiedni xi tyle, )ile jest wymaganych? Czy jest to bardziej skomplikowane?
Peter Taylor
1
@Linus \ d->f(\k->f(f d k)), ale można założyć, że wszystkie kropki mają dwa argumenty w tym wyzwaniu
BlackCap

Odpowiedzi:

4

Haskell, 163 142 133 bajtów

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

Wypróbuj na Ideone.

Nie golfowany:

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
źródło
2

Haskell, 402 289 bajtów

Dość długo, ale myślę, że to działa ..

(!)=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
źródło