Değişmez verilere sahip dillerde çift bağlantılı veya dairesel veri yapıları üzerindeki işlemleri uygulamak için geçici çözüm


11

Haskell'de nasıl grafik yapılacağını ve üzerlerinde bazı yerel işlemleri nasıl yapacağımı öğrenmek istiyorum, ancak soru Haskell'e özgü değil ve grafikler yerine iki kat bağlantılı listeleri düşünebiliriz.

Soru: Çift bağlantılı bir liste (veya başka bir çift bağlantılı veya dairesel veri yapısı) ve üzerinde işlem yapılmasını, değiştirilemez veri yapılarını (Haskell, Clojure vb.) Destekleyen ve savunan bir dilde uygulamak için deyimsel veya önerilen bir yol ne olurdu? ? Özellikle, dil tarafından resmi olarak yasaklanmış olan yerinde güncellemeler nasıl kullanılır?

Bazı yerel işlemler iki kez bağlantılı bir listede gerçekleştirilirse (örneğin, bir öğe eklenirse), dilin tembelliklerinden dolayı tüm listeyi hemen kopyalamaya gerek olmadığını kolayca hayal edebilirim. Bununla birlikte, liste iki kez bağlandığından, bir yerde değiştirilirse, eski düğümlerin hiçbiri listenin yeni sürümünde kullanılamaz ve bir şekilde er ya da geç işaretlenmeleri, kopyalanmaları, çöp toplanmaları gerekir. . Açıkçası, bunlar yalnızca listenin güncellenmiş kopyası kullanılacaksa gereksiz işlemlerdir, ancak listenin boyutuyla orantılı bir "ek yük" ekleyeceklerdir.

Bu, bu tür görevler için değiştirilemez verilerin basitçe uygunsuz olduğu ve değişebilir veriler için "yerel" desteği olmayan işlevsel bildirim dillerinin zorunlu olanlar kadar iyi olmadığı anlamına mı geliyor? Veya bazı zor bir çözüm var mı?

PS: Bu konuda internette bazı makaleler ve sunumlar buldum, ancak onları takip etmekte zorlandım, bu sorunun cevabının birden fazla paragraf ve belki de bir diyagram almaması gerektiğini düşünüyorum ... Yani, eğer varsa Bu sorunun "işlevsel" bir çözümü yok, cevap muhtemelen "kullanım C" dir. Bir tane varsa, o zaman ne kadar karmaşık olabilir?


İlgili sorular


İlgili alıntılar

Tamamen işlevsel programlama dilleri, birçok algoritmanın çok kısaca ifade edilmesine izin verir, ancak yerinde güncellenebilir durumun çok önemli bir rol oynadığı görülen birkaç algoritma vardır. Bu algoritmalar için, güncellenebilir durumdan yoksun olan tamamen işlevsel diller doğal olarak verimsiz görünmektedir ( [Ponder, McGeer ve Ng, 1988] ).

- John Launchbury ve Simon Peyton Jones, Lazy fonksiyonel devlet konuları (1994), ayrıca John Launchbury ve Simon Peyton Jones, Devlet Haskell (1995). Bu makaleler STHaskell'de monadik tip yapıcıyı tanıttı .


4
Önerilen: Okasaki
Robert Harvey

2
Referans için teşekkürler. Tezini buldum .
Alexey

Bu makale umut verici görünüyor: Haskell'de (1994), David King ve John Launchbury'nin tembel derinlik-ilk arama ve doğrusal grafik algoritmaları .
Alexey

Dizilerle benzer bir sorun, türü uygulayan diffarray paketi tarafından ele alınmaktadır DiffArray. Baktığımızda kaynağın ait diffarray paketin i 91 oluşumlarını bkz unsafePerformIO. Sorumun cevabı "evet, hayır, değişmez verilerle tamamen işlevsel diller normalde yerinde güncellemelere dayanan algoritmaları uygulamak için uygun değil" gibi görünüyor.
Alexey

(Haskell) En güncel çözelti bir sözlük (kullanmaktır Map, IntMapya da HashMapbir depolama gibi) ve düğümlerin bağlı düğüm kimlikleri içeren yapmak için. "Bilgisayar bilimindeki tüm problemler başka bir dolaylama seviyesi ile çözülebilir."
Alexey

Yanıtlar:


6

Özel görevinize uyan, ancak çift bağlantılı bir liste (ne yazık ki değişebilirliği nedeniyle eşzamanlı değişiklik hatalarına yatkın olan) kadar genel olmayan başka verimli değişmez veri yapıları olabilir . Sorununuzu daha dar bir şekilde belirtirseniz, muhtemelen böyle bir yapı bulunabilir.

Değişmez yapıların (nispeten) ekonomik geçişinin genel cevabı lenslerdir. Fikir, değiştirilmemiş bir yapıyı değiştirilmemiş parçalarından ve şu anda değiştirilmiş parçadan yeniden inşa etmek ve üzerinde komşu bir düğüme gitmek için yeterli bilgiyi saklayabilmenizdir.

Bir başka kullanışlı yapı bir fermuardır . (Komik kısım, bir lens fermuarı için tip imzasının, yapının tip imzasının bir okul-matematik türevi olmasıdır.)

İşte birkaç bağlantı.


1
ne gerek bağlı olarak bir fermuar da yararlı olabilir
jk.

Sorunumu daha dar bir şekilde belirtmek için, bir grafik yeniden yazma sistemi, örneğin grafik yeniden yazmaya dayalı bir lambda hesabı değerlendiricisi programlamak istediğimi varsayalım.
Alexey

1
@Alexey: Temiz insanların grafik yeniden yazma konusundaki çalışmalarına aşina mısınız? wiki.clean.cs.ru.nl/…
Giorgio

1
@Alexey: Bildiğimden değil: Clean, kendi başına geliştirilen bir Haskell'in kuzeni. Ayrıca yan etkilerle başa çıkmak için farklı bir mekanizmaya sahiptir (AFAIK buna benzersiz tipler denir). Öte yandan, geliştiriciler grafik yeniden yazma ile çok çalıştılar. Bu nedenle, hem grafik yeniden yazma hem de fonksiyonel programlama hakkında bilen en iyi insanlar arasında olabilirler.
Giorgio

1
Şu anda bulunduğum yerde gezinmek ve değiştirmek istediğimde, bir fermuarın iki kat bağlantılı bir liste veya bir ağaçla sorunu çözdüğünü kabul ediyorum, ancak birkaç noktaya odaklanmak istiyorsam ne yapacağım açık değil aynı anda ve örneğin iki elemanı birbirinden uzak iki yerde değiştirin. "Dairesel" yapılarda kullanılıp kullanılamayacağı daha da az açıktır.
Alexey

2

Haskell değiştirilebilir veri yapılarının kullanımını engellemez. Bunları kullanan kod bölümlerinin sonunda bir G / Ç eylemi döndürmesi (eninde sonunda ana işlev tarafından döndürülen G / Ç eylemine bağlanması gerekir) nedeniyle çok cesaret kırılır ve kullanımı zorlaştırılır, ancak bu gerçekten ihtiyacınız varsa bu tür yapıları kullanmayı imkansız hale getirin.

İleriye dönük bir yol olarak yazılım işlem belleğinin kullanımını araştırmanızı öneririm. Değişken yapıları uygulamak için etkili bir yol sağlamanın yanı sıra, iplik güvenliği için de çok faydalı garantiler sağlar. Modülünde açıklamasına bakın https://hackage.haskell.org/package/stm ve en wiki bakış https://wiki.haskell.org/Software_transactional_memory .


Teşekkürler, STM hakkında bilgi edinmeye çalışacağım. Mutability ve devlet (i stumbles ettik olması Haskell daha yöntem vardır gibi görünüyor MVar, State, ST) i farklılıklarına dışarı rakam gerekiyor ve kullanım amaçları edeceğiz böylece.
Alexey

@Alexey: İyi bir nokta ST, IMO cevabında belirtilmelidir, çünkü durumsal bir hesaplama yapmaya, daha sonra durumu atmaya ve sonucu saf bir değer olarak çıkarmaya izin verir.
Giorgio

@Giorgio, Haskell'in STSTM ile birlikte kullanılması hem eşzamanlılık hem de tek kullanımlık duruma sahip olmak mümkün mü?
Alexey

Bir terminoloji önerisi daha var: oluşturulan ana IO eylemi " ana işlev tarafından döndürülmüyor " ama maindeğişkene atanmış . :) ( mainbir işlevi bile tutmaz.)
Alexey

Ben senin fikrini görüyorum, ama yine de "değişken" çoğu insanın zihninde bir değer üreten bir süreçten ziyade basit bir değer olarak bir çağrışım vardır ve ana açıkça öncekinden ziyade ikincisi olarak daha iyi düşünülür. Önerdiğiniz değişiklik, teknik olarak doğru olsa da, konuyla yabancı olanları şaşırtma potansiyeline sahiptir.
Jules
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.