แปลง pointfree เป็น pointful


9

ในฐานะที่เป็นแฮ็กเกอร์ Haskell ฉันชอบสัญกรณ์ pointfree มากกว่าประเด็น น่าเสียดายที่บางคนพบว่าโน้ตที่ไม่มีจุดอ่านยากที่จะอ่านและฉันพบว่ามันยากที่จะรับวงเล็บที่ถูกต้องเมื่อฉันเขียนแบบไม่มีจุดหมาย ช่วยฉันแปลงโค้ดที่เขียนด้วย pointfree เป็นเครื่องหมายที่ไม่มีจุดหมาย!

เกี่ยวกับ

ในสัญกรณ์ pointfree เราใช้ points (ใช่จริง ๆ ) เพื่อป้อนข้อมูลผลลัพธ์ของฟังก์ชันหนึ่งไปยังอีกฟังก์ชัน พูดว่าถ้าคุณมีฟังก์ชั่น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 เราใช้ points เพื่อดึงเอาท์พุทของฟังก์ชั่นหนึ่งไปยังอีกฟังก์ชั่นนั่นชัดเจนว่าความพยายามที่จะพิสูจน์ว่า pointfree นั้นไม่มีจุดหมาย
Luis Mendo

1
"Pointfree ใช้งานได้กับฟังก์ชั่นที่รับพารามิเตอร์เดียวเท่านั้น" นั่นไม่เป็นความจริง: (+).(*3)เหมือนกับ\x y->3*x+y
ดาเมียน

2
@ Damien ฉันพยายามทำให้ความท้าทายเข้าถึงได้มากขึ้น คุณยังสามารถทำสิ่งต่าง ๆ เช่นนกฮูก(.).(.)ซึ่งแปลงเป็น\i b c f -> i (b c f)
BlackCap

2
ดังนั้นเพื่อความชัดเจนสำหรับผู้ที่ไม่รู้จักไวยากรณ์ของ Haskell ด้วยหัวใจ: อันดับแรกเราควรจับคู่วงเล็บในอินพุตและเรียกคืนในแต่ละนิพจน์วงเล็บระดับบนสุด จากนั้นแทนที่แต่ละอัน.ด้วย a (, เติม a \xและผนวกส่วนที่เกี่ยวข้องxและมาก)เท่าที่ต้องการ? หรือมันมีความซับซ้อนมากกว่านั้น?
Peter Taylor

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

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

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.