ฉันจะทำอย่างไรกับ callCC ที่ไม่สามารถดำเนินการต่อได้


9

ฉันกำลังต่อสู้กับความเข้าใจ callCC จริงๆ ฉันได้รับพลังแห่งการสานต่อและฉันใช้แนวคิดนี้ในบางโครงการของฉันเพื่อสร้างแนวคิดเจ๋ง ๆ cont :: ((a->r)->r)-> Cont r aแต่ไม่เคยมีฉันต้องการที่จะใช้สิ่งที่มีความสามารถมากกว่า

หลังจากใช้แล้วมันสมเหตุสมผลมากว่าทำไมพวกเขาถึงเรียก Cont Cont ว่าเป็นแม่ของ monads ทั้งหมดใช่เลยฉันไม่เข้าใจว่าจะต้องใช้เมื่อไรcallCCและนั่นคือคำถามของฉัน


คุณใช้งานContอย่างไร? เมื่อคุณบอกว่าคุณไม่จำเป็นต้องใช้สิ่งที่มีประสิทธิภาพมากกว่าcontนั่นหมายความว่าคุณไม่ได้ใช้resetหรือshiftไม่?
KA Buhr

ฉันไม่ได้ใช้หรือreset shiftฉันใช้มันเพื่อกำหนดภาษา eembedded ที่สามารถหยุดชั่วคราวได้จนกว่าการกระทำที่กำหนดจะได้รับการแก้ไขโดยกระบวนการอื่นและจากนั้นจะดำเนินการต่อด้วย "การต่อเนื่อง" ที่กำหนด บางทีฉันอาจจะให้ความประทับใจกับการมีประสบการณ์มากมายกับ Cont Monad แต่ไม่มากจริง ๆ ฉันแค่อยากจะเข้าใจ callCC
Alejandro Navas

คำตอบ:


10

callCC ช่วยให้คุณ "กลับต้น" ความหมาย แต่ในบริบท monadic

สมมติว่าคุณต้องการdoOneและถ้าสิ่งนั้นกลับTrueมาคุณจะหยุดทันทีไม่เช่นนั้นคุณจะไปที่doTwoและdoThree:

doOne :: Cont r Bool
doTwo :: Cont r ()
doThree :: Cont r ()

doThings :: Cont r ()
doThings = do
    one <- doOne
    if one
        then pure ()
        else do
            doTwo
            doThree

เห็นว่าการifแตกแขนงนั่น? สาขาเดียวนั้นไม่เลวที่สามารถจัดการได้ แต่ลองนึกภาพว่ามีหลายจุดที่คุณต้องการประกันตัว สิ่งนี้จะได้รับอย่างรวดเร็วน่าเกลียดมาก

ด้วยcallCCคุณสามารถมี "ผลตอบแทนเร็ว": คุณประกันตัวที่จุดแตกกิ่งและไม่ต้องทำส่วนที่เหลือของการคำนวณ:

doThings = callCC \ret -> do
    one <- doOne
    when one $ ret ()
    doTwo
    doThree

น่าอ่านมากขึ้น!

ที่สำคัญเนื่องจากretที่นี่ไม่ได้เป็นรูปแบบพิเศษ (เช่นreturnในภาษา C-like) แต่มีค่าเหมือนกันคุณสามารถส่งต่อไปยังฟังก์ชั่นอื่น ๆ ได้เช่นกัน! และฟังก์ชั่นเหล่านั้นสามารถทำสิ่งที่เรียกว่า "การส่งคืนที่ไม่ใช่ของท้องถิ่น" - นั่นคือพวกเขาสามารถ "หยุด" การdoThingsคำนวณแม้กระทั่งจากการเรียกซ้อนหลาย ๆ ครั้ง ตัวอย่างเช่นฉันสามารถdoOneแยกแยะการตรวจสอบผลลัพธ์ของฟังก์ชันแยกต่างหากcheckOneเช่นนี้:

checkOne ret = do
    one <- doOne
    when one $ ret ()

doThings = callCC \ret -> do
    checkOne ret
    doTwo
    doThree

ฉันเข้าใจแล้ว! และbเป็นเพียงสัญลักษณ์แทนเพื่อให้คุณสามารถเชื่อมต่อภายใน callCC ได้มากขึ้น อย่างไรก็ตามเมื่อretถูกนำไปใช้ต่อเนื่องที่ผลิตโดยซีซีโทรจะกลับ "" retสิ่งที่ถูกขังอยู่ใน มันค่อนข้างซับซ้อน แต่ก็ฉลาด แต่มีพลังมากฉันไม่เห็นสถานที่ที่ใช้พลังงานเช่นนั้นไม่เหมือนกับการฆ่าแมลงด้วยนิก
Alejandro Navas

1
@caeus ดีใจที่ฉันสามารถช่วย หากคุณชอบคำตอบของฉันคุณจะลองตอบรับหรือไม่?
Fyodor Soikin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.