Cont ile yapılamayan callCC ile ne yapabilirim?


9

Gerçekten gerçekten callCC'yi anlamakta zorlanıyorum. Sürekliliklerin gücünü alıyorum ve bazı projelerimde bu konsepti harika konseptler oluşturmak için kullanıyorum. Ama asla daha büyük yeteneklere sahip bir şey kullanmam gerekmedi cont :: ((a->r)->r)-> Cont r a.

Kullandıktan sonra, Cont Monad'ı neden tüm monadların annesi olarak adlandırdıkları çok mantıklı, YET, ne zaman kullanmam gerekecek callCC, ve bu tam olarak benim sorum.


Nasıl kullandın Cont? Bundan daha güçlü bir şey kullanmanız gerekmediğini söylediğinizde cont, bu, kullanmadığınız resetveya shiftikisinden birini kullanmadığınız anlamına mı geliyor ?
KA Buhr

Ben kullanmadım resetya shift. Belirli bir eylem başka bir işlem tarafından çözülene kadar askıya alınabilen bir eembed dili tanımlamak için kullandım ve sonra verilen "devam" ile devam eder. Belki Cont Monad ile çok fazla deneyime sahip olduğum izlenimini veriyorum, ama o kadar da değil, sadece callCC'yi anlamak istiyorum
Alejandro Navas

Yanıtlar:


10

callCC size "erken dönüş" semantiği verir, ancak monadik bir bağlamda.

İstediğinizi söyleyin doOneve eğer bu geri dönerse Truederhal durursunuz, aksi takdirde devam edersiniz doTwove 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

Görüyor iforada dallanma? Bir dal o kadar da kötü değil, halledilebilir, ama sadece kefalet etmek istediğiniz bu tür birden fazla nokta olduğunu hayal edin? Bu çok çabuk çok çirkinleşiyor.

İle callCC"erken dönüş" olabilir: dallanma noktasında kefalet ve hesaplamanın geri kalanını yuvalamak zorunda değilsiniz:

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

Okumak çok daha hoş!

Daha da önemlisi, retburada özel bir sözdizimi olmadığı için ( returnC benzeri dillerde olduğu gibi), ancak diğer herhangi bir değer gibi, onu diğer işlevlere de aktarabilirsiniz! Ve bu işlevler daha sonra "yerel olmayan dönüş" olarak adlandırılanları gerçekleştirebilir - yani doThings, birden çok iç içe çağrıdan bile hesaplamayı "durdurabilir" . Örneğin, doOne's sonucunu şöyle ayrı bir işlev içine kontrol etmeyi faktör olabilir checkOne:

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

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

Anladım! ve btemel olarak sadece bir joker karakterdir, böylece callCC içinde daha fazla sürekliliği zincirleyebilirsiniz. Her neyse, bir kez retuygulandığında, cc çağrısı tarafından üretilen devam, konulan her şeyi "geri döndürecektir" ret. Oldukça kıvrımlı, ama oldukça akıllı, ama son derece güçlü Böyle bir gücü kullanmanın bir nuke ile bir sinek öldürmek gibi olmadığı pek çok yer görmüyorum
Alejandro Navas

1
@caeus Yardım edebileceğim için mutluyum. Cevabımı beğendiyseniz, kabul etmeyi düşünür müsünüz?
Fyodor Soikin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.