วิธีแก้ปัญหาสำหรับการใช้งานการดำเนินการเกี่ยวกับโครงสร้างข้อมูลที่เชื่อมโยงหรือวงกลมในภาษาที่มีข้อมูลที่ไม่เปลี่ยนรูปแบบ


11

ฉันต้องการเรียนรู้วิธีสร้างกราฟและดำเนินการบางอย่างกับพวกเขาใน Haskell แต่คำถามนั้นไม่เฉพาะเจาะจงกับ Haskell และแทนที่จะเป็นกราฟเราอาจพิจารณาเชื่อมโยงรายการเป็นสองเท่า

คำถาม: อะไรจะเป็นสำนวนหรือแนะนำวิธีการใช้รายการเชื่อมโยงทวีคูณ (หรืออื่น ๆ ที่เชื่อมโยงทวีคูณหรือโครงสร้างข้อมูลแบบวงกลม) และการดำเนินงานในภาษาที่สนับสนุนและสนับสนุนสำหรับโครงสร้างข้อมูลที่ไม่เปลี่ยนรูปแบบ (Haskell, Clojure เป็นต้น) ? โดยเฉพาะอย่างยิ่งวิธีการใช้การอัปเดตในสถานที่ซึ่งภาษาต้องห้ามอย่างเป็นทางการ?

ฉันสามารถจินตนาการได้อย่างง่ายดายว่าหากมีการดำเนินการในท้องถิ่นในรายการที่ลิงก์ซ้ำกัน (หากมีการแทรกรายการไว้) อาจไม่จำเป็นต้องคัดลอกรายการทั้งหมดทันทีเนื่องจากความเกียจคร้านของภาษา อย่างไรก็ตามเนื่องจากรายการมีการเชื่อมโยงเป็นสองเท่าหากมีการแก้ไขในที่เดียวจึงไม่มีโหนดเก่าที่สามารถใช้ในรายการเวอร์ชันใหม่และพวกเขาจะต้องทำเครื่องหมายคัดลอกคัดลอกเก็บขยะไม่ช้า . เห็นได้ชัดว่าสิ่งเหล่านี้เป็นการดำเนินการที่ซ้ำซ้อนหากจะใช้เฉพาะสำเนาที่ปรับปรุงแล้วของรายการ แต่พวกเขาจะเพิ่มสัดส่วน "ค่าใช้จ่าย" ตามขนาดของรายการ

นี่หมายความว่าสำหรับงานดังกล่าวข้อมูลที่ไม่เปลี่ยนรูปแบบนั้นไม่เหมาะสมและภาษาที่ประกาศได้โดยไม่ต้องมีการสนับสนุน "ดั้งเดิม" สำหรับข้อมูลที่ไม่แน่นอนไม่ดีเท่าที่จำเป็นหรือไม่? หรือมีวิธีแก้ปัญหาที่ยุ่งยากบ้างไหม?

ป.ล. ฉันได้พบบทความและงานนำเสนอบางอย่างเกี่ยวกับเรื่องนี้ในอินเทอร์เน็ต แต่มีความยากลำบากในการติดตามพวกเขาในขณะที่ฉันคิดว่าคำตอบของคำถามนี้ไม่ควรใช้มากกว่าหนึ่งย่อหน้าและอาจเป็นไดอะแกรม ... ฉันหมายถึงถ้ามี ไม่มีวิธีแก้ปัญหา "ฟังก์ชั่น" สำหรับปัญหานี้คำตอบน่าจะเป็น "ใช้ C" หากมีอย่างใดอย่างหนึ่งมันจะซับซ้อนแค่ไหน?


คำถามที่เกี่ยวข้อง


ใบเสนอราคาที่เกี่ยวข้อง

ภาษาการเขียนโปรแกรมที่ใช้งานได้จริงช่วยให้อัลกอริธึมหลายอย่างแสดงออกมาอย่างกระชับ แต่มีอัลกอริธึมบางอย่างที่สถานะที่สามารถอัปเดตได้ในสถานที่ดูเหมือนจะมีบทบาทสำคัญ สำหรับอัลกอริทึมเหล่านี้ภาษาที่ใช้งานได้จริงซึ่งไม่มีสถานะที่สามารถอัปเดตได้ดูเหมือนจะไม่มีประสิทธิภาพโดยแท้จริง ( [Ponder, McGeer และ Ng, 1988] )

- John Launchbury และ Simon Peyton Jones, Lazy functional threads (1994), John Launchbury และ Simon Peyton Jones, Haskell (1995) เอกสารเหล่านี้แนะนำตัวSTสร้างประเภท monadic ใน Haskell


4
แนะนำ: Okasaki
Robert Harvey

2
ขอบคุณสำหรับการอ้างอิง ฉันพบวิทยานิพนธ์ของเขาแล้ว
Alexey


ดูเหมือนว่าปัญหาที่คล้ายกันกับอาร์เรย์จะได้รับการแก้ไขโดยแพคเกจdiffarrayที่ใช้DiffArrayประเภท มองไปที่แหล่งที่มาของdiffArrayแพคเกจ 91 unsafePerformIOฉันเห็นการเกิดขึ้นของ ดูเหมือนว่าคำตอบสำหรับคำถามของฉันคือ "ใช่ไม่ใช่ภาษาที่ใช้งานได้จริงกับข้อมูลที่ไม่เปลี่ยนรูปแบบไม่เหมาะสมสำหรับการใช้อัลกอริทึมที่โดยปกติแล้วใช้การอัปเดตแบบแทนที่"
Alexey

วิธีการแก้ปัญหาปัจจุบันของฉัน (ใน Haskell) คือการใช้พจนานุกรม ( Map, IntMapหรือHashMap) ในขณะที่การจัดเก็บข้อมูลและเพื่อให้โหนดมีรหัสของโหนดที่เชื่อมโยง "ปัญหาทั้งหมดในวิทยาการคอมพิวเตอร์สามารถแก้ไขได้โดยการอ้อมอีกระดับ
Alexey

คำตอบ:


6

อาจมีโครงสร้างข้อมูลที่ไม่เปลี่ยนรูปแบบอื่น ๆ ที่เหมาะสมกับงานของคุณโดยเฉพาะ แต่ไม่เหมือนกับรายการที่เชื่อมโยงเป็นสองเท่า (ซึ่งน่าเสียดายที่มีข้อบกพร่องในการปรับเปลี่ยนพร้อมกันเนื่องจากความไม่แน่นอน หากคุณระบุปัญหาของคุณให้แคบลงอาจพบโครงสร้างดังกล่าวได้

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

อีกโครงสร้างที่มีประโยชน์เป็นซิป (ส่วนที่ตลกคือลายเซ็นประเภทสำหรับซิปเลนส์เป็นอนุพันธ์ทางคณิตศาสตร์ในโรงเรียนของลายเซ็นประเภทของโครงสร้าง)

นี่คือลิงค์ไม่กี่


1
ขึ้นอยู่กับสิ่งที่จำเป็นต้องใช้ซิปอาจมีประโยชน์เช่นกัน
jk

หากต้องการระบุปัญหาของฉันให้แคบลงสมมติว่าฉันต้องการเขียนโปรแกรมระบบการเขียนกราฟใหม่เช่นตัวคำนวณแคลคูลัสแลมบ์ดาจากการเขียนกราฟใหม่
Alexey

1
@Alexey: คุณคุ้นเคยกับงาน Clean people ในการเขียนกราฟใหม่หรือไม่? wiki.clean.cs.ru.nl/…
Giorgio

1
@Alexey: ไม่ใช่ที่ฉันรู้: Clean เป็นลูกพี่ลูกน้องของ Haskell ที่พัฒนาขึ้นมาเอง นอกจากนี้ยังมีกลไกที่แตกต่างกันในการจัดการกับผลข้างเคียง (AFAIK เรียกว่าประเภทเฉพาะ) ในทางกลับกันนักพัฒนาซอฟต์แวร์ได้ทำงานอย่างมากมายกับการเขียนกราฟใหม่ ดังนั้นพวกเขาจึงอาจเป็นหนึ่งในบุคคลที่ดีที่สุดที่รู้จักทั้งการเขียนกราฟและการเขียนโปรแกรมเชิงฟังก์ชัน
Giorgio

1
ฉันยอมรับว่าซิปดูเหมือนว่าจะแก้ปัญหาด้วยรายการที่เชื่อมโยงเป็นสองเท่าหรือต้นไม้ถ้าฉันต้องการนำทางและแก้ไขที่จุดที่ฉันอยู่ในขณะนี้ แต่ไม่ชัดเจนว่าจะทำอย่างไรถ้าฉันต้องการมุ่งเน้นไปที่จุดต่าง ๆ พร้อมกันและตัวอย่างเช่นสลับสององค์ประกอบในสองแห่งห่างกัน มีความชัดเจนน้อยลงหากสามารถใช้กับโครงสร้าง "แบบวงกลม"
Alexey

2

Haskell ไม่ได้ป้องกันการใช้โครงสร้างข้อมูลที่ไม่แน่นอน พวกเขามีกำลังใจอย่างหนักและทำให้ยากต่อการใช้งานเนื่องจากความจริงที่ว่าส่วนของรหัสที่ใช้พวกเขาในที่สุดจะต้องส่งคืนการกระทำ IO (ซึ่งในที่สุดจะต้องผูกพันกับการกระทำ IO ที่ส่งกลับโดยฟังก์ชั่นหลัก) ทำให้ไม่สามารถใช้โครงสร้างดังกล่าวได้หากคุณต้องการจริงๆ

ฉันขอแนะนำให้ตรวจสอบการใช้หน่วยความจำทรานแซคชันของซอฟต์แวร์เป็นวิธีในอนาคต เช่นเดียวกับการจัดหาวิธีที่มีประสิทธิภาพในการใช้โครงสร้างที่เปลี่ยนแปลงได้มันยังให้การรับประกันที่มีประโยชน์มากสำหรับความปลอดภัยของเธรด ดูรายละเอียดของโมดูลที่https://hackage.haskell.org/package/stmและภาพรวมของวิกิพีเดียที่https://wiki.haskell.org/Software_transactional_memory


ขอบคุณฉันจะพยายามเรียนรู้เกี่ยวกับ STM ดูเหมือนว่ามีวิธีการอื่น ๆ ใน Haskell จะมีความผันแปรและรัฐ (ผมเคยสะดุดMVar, State, ST) ดังนั้นผมจะต้องคิดออกความแตกต่างและการใช้งานของพวกเขาตั้งใจ
Alexey

@Alexey: จุดที่ดีเกี่ยวกับSTIMO มันควรจะกล่าวถึงในคำตอบเพราะช่วยให้การคำนวณแบบ stateful แล้วละทิ้งรัฐและแยกผลเป็นค่าบริสุทธิ์
Giorgio

@Giorgio เป็นไปได้หรือไม่ที่จะใช้ Haskell STกับ STM เพื่อให้เกิดภาวะพร้อมกันและใช้ครั้งเดียว?
Alexey

คำแนะนำศัพท์เพิ่มเติมเพียงหนึ่งคำสั่ง: การกระทำหลักของ IO ที่ได้รับการจัดเตรียมนั้นไม่ใช่ " ส่งคืนโดยฟังก์ชันหลัก" แต่ถูกกำหนดให้กับmainตัวแปร :) ( mainไม่มีฟังก์ชั่นค้างไว้)
Alexey

ฉันเห็นประเด็นของคุณ แต่ยังคง "แปรปรวน" มีความหมายแฝงอยู่ในใจของคนส่วนใหญ่ว่าเป็นคุณค่าง่าย ๆ แทนที่จะเป็นกระบวนการที่สร้างคุณค่าและหลักคิดได้ชัดเจนกว่าในอดีต การเปลี่ยนแปลงที่คุณแนะนำในขณะที่ถูกต้องทางเทคนิคอย่างชัดเจนมีความเป็นไปได้ที่จะสร้างความสับสนให้ผู้ที่ไม่คุ้นเคยกับเรื่อง
จูลส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.