Konversi pointfree ke pointful

9

Menjadi seorang peretas Haskell, saya lebih suka notasi pointfree daripada pointful. Sayangnya beberapa orang menemukan notasi pointfree sulit dibaca, dan saya merasa sulit untuk mendapatkan jumlah tanda kurung yang benar ketika saya menulis dalam pointful. Bantu saya mengonversi kode yang ditulis dalam pointfree ke notasi pointful!

Tentang

Dalam notasi pointfree kami menggunakan poin (ya, sungguh) untuk memberi makan output dari satu fungsi ke yang lain. Katakanlah, jika Anda memiliki fungsi succyang mengambil angka dan menambahkan 1 ke dalamnya, dan Anda ingin membuat fungsi yang menambahkan 3 ke angka, alih-alih melakukan ini:

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

Anda bisa melakukan ini:

succ.succ.succ

Pointfree hanya bekerja dengan fungsi-fungsi yang mengambil parameter tunggal (dalam tantangan ini pula), jadi jika fungsi kita tidak succtetapi addmengambil 2 angka dan menambahkannya bersama-sama, kita harus memberinya argumen sampai hanya ada satu yang tersisa:

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

Terakhir, fungsi dapat menggunakan fungsi lain sebagai argumen:

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

Input dan output yang diharapkan

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

Aturan

  • Output Anda mungkin memiliki lebih banyak spasi atau tanda kurung dari yang dibutuhkan, asalkan seimbang
  • Anda tidak harus memastikan bahwa nama variabel yang Anda buat \xbelum digunakan di tempat lain dalam kode
  • Ini adalah pilihan Anda apakah akan membuat suatu fungsi atau program penuh
  • Ini codegolf, kode terpendek dalam byte menang!

Anda mungkin menemukan manfaat yang tumpul, itu mengkonversi antara dua notasi (tetapi juga faktorisasi kode bila mungkin): https://blunt.herokuapp.com

BlackCap
sumber
15
Dalam notasi pointfree, kami menggunakan poin untuk mengumpankan output dari satu fungsi ke fungsi lain. Itu jelas merupakan upaya untuk membuktikan bahwa pointfree tidak sia
Luis Mendo
1
"Pointfree hanya berfungsi dengan fungsi yang mengambil satu parameter". Itu tidak benar: (+).(*3)sama dengan\x y->3*x+y
Damien
2
@ Damen Saya mencoba membuat tantangan lebih mudah diakses. Anda juga dapat melakukan hal-hal seperti burung hantu: (.).(.)yang mengonversi ke\i b c f -> i (b c f)
BlackCap
2
Jadi untuk kejelasan bagi mereka yang tidak tahu sintaksis Haskell dengan hati: pertama-tama kita harus mencocokkan tanda kurung di input dan berulang pada setiap ekspresi kurung tingkat atas; dan kemudian ganti masing .- masing dengan (, tambahkan \xdan tambahkan yang sesuai xdan sebanyak )yang diperlukan? Atau lebih rumit dari itu?
Peter Taylor
1
@Linus \ d->f(\k->f(f d k)), tetapi Anda dapat mengasumsikan bahwa semua titik diberi dua argumen dalam tantangan ini
BlackCap

Jawaban:

4

Haskell, 163 142 133 byte

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

Cobalah di Ideone.

Tidak Disatukan:

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

Haskell, 402 289 byte

Cukup lama, tapi saya pikir itu berhasil ..

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