การใช้คำตอบที่ดีของ jbapple เกี่ยวกับการreplicate
ใช้riffing แทนreplicateA
(ซึ่งreplicate
สร้างขึ้นบน) แทนที่จะทำตามขั้นตอนต่อไปนี้:
--Unlike fromList, one needs the length explicitly.
myFromList :: Int -> [b] -> Seq b
myFromList l xs = flip evalState xs $ Seq.replicateA l go
where go = do
(y:ys) <- get
put ys
return y
myFromList
(ในรุ่นเล็กน้อยมีประสิทธิภาพมากขึ้น) เป็นที่เรียบร้อยแล้วกำหนดและใช้ภายในในData.Sequence
การสร้างต้นไม้นิ้วที่มีผลการทุกประเภท
โดยทั่วไปแล้วสัญชาตญาณของreplicateA
เรื่องง่าย replicateA
ถูกสร้างขึ้นที่ด้านบนของฟังก์ชั่นapplicativeTree applicativeTree
รับต้นไม้ขนาดหนึ่งชิ้นm
และสร้างต้นไม้ที่มีความสมดุลซึ่งบรรจุn
สำเนาของสิ่งนี้ เคสสำหรับn
มากถึง 8 ( Deep
นิ้วเดียว) นั้นเขียนโค้ดแบบยาก อะไรก็ตามที่อยู่เหนือสิ่งนี้และมันจะเรียกตัวเองซ้ำ ๆ องค์ประกอบ "การใช้งาน" เป็นเพียงการแทรกการสร้างต้นไม้ที่มีเอฟเฟกต์เกลียวผ่านเช่นในกรณีของรหัสข้างต้นรัฐ
go
ฟังก์ชั่นซึ่งถูกจำลองเป็นเพียงการกระทำที่ได้รับสถานะปัจจุบันปรากฏองค์ประกอบปิดด้านบนไปและแทนที่ส่วนที่เหลือ ในการร้องขอแต่ละครั้งจะมีขั้นตอนเพิ่มเติมในรายการที่ให้ไว้เป็นอินพุต
หมายเหตุที่เป็นรูปธรรมมากขึ้น
main = print (length (show (Seq.fromList [1..10000000::Int])))
ในการทดสอบแบบง่าย ๆ สิ่งนี้ให้ผลการปฏิบัติที่น่าสนใจ หน้าที่หลักข้างต้นวิ่งเกือบ 1/3 ที่ต่ำกว่าด้วย myFromList fromList
กว่าด้วย ในทางกลับกันmyFromList
ใช้ฮีปคงที่ 2MB ในขณะที่มาตรฐานfromList
ใช้สูงสุด 926MB 926MB นั้นเกิดขึ้นจากต้องเก็บรายชื่อทั้งหมดไว้ในหน่วยความจำพร้อมกัน ในขณะเดียวกันการแก้ปัญหาด้วยmyFromList
สามารถที่จะใช้โครงสร้างในแบบสตรีมมิ่งขี้เกียจ ปัญหาเกี่ยวกับความเร็วเป็นผลมาจากความจริงที่ว่าmyFromList
จะต้องดำเนินการจัดสรรเป็นสองเท่าโดยประมาณfromList
. เราสามารถกำจัดการจัดสรรเหล่านั้นได้ด้วยการย้ายไปที่ Monad ที่เปลี่ยนรูปแบบ CPS แต่ผลลัพธ์นั้นจะทำให้หน่วยความจำมีมากขึ้นในเวลาใดก็ตามเนื่องจากการสูญเสียความขี้เกียจนั้นต้องผ่านรายการในลักษณะที่ไม่ได้สตรีม
ในทางตรงกันข้ามถ้าแทนที่จะบังคับให้ลำดับทั้งหมดด้วยการแสดงฉันจะย้ายไปที่การแยกส่วนหัวหรือองค์ประกอบสุดท้ายmyFromList
นำเสนอการชนะที่ยิ่งใหญ่ขึ้นทันที - การแยกองค์ประกอบส่วนหัวนั้นเกือบจะในทันทีและการแยกองค์ประกอบสุดท้ายคือ 0.8s . ในขณะเดียวกันด้วยมาตรฐานการfromList
แยกส่วนหัวหรือองค์ประกอบสุดท้ายใช้เวลาประมาณ 2.3 วินาที
นี่คือรายละเอียดทั้งหมดและเป็นผลมาจากความบริสุทธิ์และความเกียจคร้าน ในสถานการณ์ที่มีการกลายพันธุ์และการเข้าถึงแบบสุ่มฉันคิดว่าreplicate
วิธีแก้ปัญหานั้นจะดีกว่าอย่างเคร่งครัด
อย่างไรก็ตามมันทำให้เกิดคำถามว่ามีวิธีการเขียนapplicativeTree
เช่นmyFromList
นี้ว่ามีประสิทธิภาพมากขึ้นอย่างเคร่งครัด ปัญหาคือฉันคิดว่าการดำเนินการสมัครจะดำเนินการในลำดับที่แตกต่างจากต้นไม้ที่ถูกสำรวจโดยธรรมชาติ แต่ฉันไม่ได้ทำงานอย่างเต็มที่ผ่านวิธีการทำงานนี้หรือหากมีวิธีการแก้ปัญหานี้