Конвертировать pointfree в pointful

9

Будучи хакером на Haskell, я предпочитаю бессмысленную нотацию над точечной. К сожалению, некоторые люди считают, что бессмысленные нотации трудно читать, и мне трудно получить правильное количество скобок, когда я пишу точечно. Помогите мне преобразовать код, написанный в 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 мы используем точки для передачи вывода одной функции в другую. Это явно попытка доказать, что pointfree не бессмысленна
Луис Мендо,
1
Msgstr "Pointfree работает только с функциями, которые принимают один параметр". Это не правда: так (+).(*3)же, как\x y->3*x+y
Дэмиен
2
@Damien Я пытался сделать задачу более доступной. Вы также можете делать такие вещи, как сова: (.).(.)которая преобразуется в\i b c f -> i (b c f)
BlackCap
2
Итак, для ясности для тех, кто не знает синтаксис Haskell наизусть: мы должны сначала сопоставить круглые скобки во входных данных и использовать рекурсивные выражения в каждом выражении в скобках верхнего уровня; а затем заменить каждое .на a (, добавить a \xи добавить соответствующее xи столько, )сколько требуется? Или это сложнее, чем это?
Питер Тейлор
1
@Linus \ d->f(\k->f(f d k)), но вы можете предположить, что в этом
задании

Ответы:

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.

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
источник
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
Damien
источник