Перетворити pointfree в pointful


9

Будучи хакерським хакером, я віддаю перевагу точковому позначенню над точковим. На жаль, деяким людям важко читати нотатки, які важко читати, і мені важко отримати правильну кількість круглих дужок, коли я пишу в точці. Допоможіть мені перетворити код, написаний pointfree, в точну нотацію!

Про

У точковому позначенні ми використовуємо точки (так, насправді) для передачі результатів однієї функції в іншу. Скажіть, якщо у вас була функція, succяка приймає число і додає до неї 1, і ви хотіли зробити функцію, яка додає 3 до числа, замість цього:

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

Ви можете це зробити:

succ.succ.succ

Pointfree працює лише з функціями, які беруть один параметр, однак (у цьому виклику все одно), тож якщо наша функція не була, succа addяка бере 2 числа і додає їх разом, нам доведеться подавати аргументи, поки не залишиться лише один:

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

Нарешті, функції можуть приймати інші функції як аргументи:

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

Вхідні дані та очікуваний вихід

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

Правила

  • На виході може бути більше пробілів або круглих дужок, ніж потрібно, якщо вони врівноважені
  • Вам не потрібно переконатися, що ім’я створеної змінної \xвже не використовується десь у коді
  • Це ваш вибір, чи створити функцію чи повну програму
  • Це codegolfнайкоротший виграш коду в байтах!

Вам може бути корисним тупість, він перетворюється між двома позначеннями (але також, коли можливо, розшифровує код): https://blunt.herokuapp.com


15
У точковому позначенні ми використовуємо точки для передачі результатів однієї функції в іншу. Це очевидно спроба довести, що pointfree не є безглуздим
Луїс Мендо

1
"Pointfree працює лише з функціями, які приймають один параметр". Це неправда: (+).(*3)те саме, що\x y->3*x+y
Демієн,

2
@Damien Я намагався зробити виклик доступнішим. Ви також можете робити такі речі, як сова: (.).(.)яка перетворюється на\i b c f -> i (b c f)
BlackCap

2
Отже, для наочності для тих, хто не знає синтаксису Haskell напам'ять: ми повинні спочатку зіставити дужки у вхідних даних і повторити повторне використання кожного викладу в верхньому рівні; а потім замініть кожне .на (, додайте а \xта додайте відповідне xта стільки, )скільки потрібно? Або це складніше за це?
Пітер Тейлор

1
@Linus \ d->f(\k->f(f d k)), але можна припустити, що всі точки в цьому виклику подаються два аргументи
BlackCap

Відповіді:


4

Haskell, 163 142 133 байт

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

Спробуйте це на Ideone.

Безголівки:

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

2

Haskell, 402 289 байт

Досить довго, але я думаю, що це працює ..

(!)=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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.