7

Ben Word32, String (curry'i yok say) ve IO Word32 çıktıları gibi birkaç parametre alan haskell'de bir işlev yazdım. Şimdi, bu işlevi işlevinin gerçek anlamda: aynı girişler için, çıktı her zaman aynı olacaktır. Yan etkisi yoktur. Word32 yerine IO Word32 işlevini döndürmesinin nedeni, son Word32 çıktısını hesaplamak için fonksiyonun birçok 32 bit Doğrusal Geri Besleme Kaydırma kaydının (lfsr) ve diğer yazmaçların bir döngüde birkaç kez güncelleştirmesidir.'State' (Evet) 'i gizlemeksizin bir haskell işlevi nasıl yazılır' state '(değişiklik) durumu değiştirir

Sorum şu: Bu işlev 'un etkin bir şekilde hiçbir yan etkisi olmadığı göz önüne alındığında, bu kayıt defteri güncellemelerini işlev uygulamasında gizlemek mümkün mü, bu işlev, Word32 ve IO Word32 döndürmüyor? Öyleyse nasıl?

+0

FFI tarafından içe aktarılıyor mu? – fuz

+1

Fonksiyonun gövdesinin zorunlu olarak kısmi olarak yazıldığını ve LSFR'leri tutmak için yerel olarak tanımlanmış IORef'i kullandığımı doğru mu anlıyoruz? Belki de yerine “STREF” kullanmayı düşünmeli ve hesaplamayı bir “ST” monad içinde çalıştırmalısınız. – rkhayrov

+1

İşleviniz için kod yazabilir misiniz? Belki de ilk etapta IO olmalıdır. – augustss

cevap

13

Evet! Haskell bunu yapabilir. tamamen işlev dışındaki gözlemci gizlenir

ST monad

aslında değişken durumunu (kayıtları) kullanırsanız, o zaman, the ST monad hafıza etkileri yalnızca bir monad vardır. ST dünyasına runST aracılığıyla girdiğinizde, fonksiyondan çıktığınızda, tüm efektlerin görünmeyecekleri garanti edilir.

Tam olarak, yerel, değiştirilebilen durumla çalışmak için doğru hesaplama ortamıdır.

Tamamen fonksiyonel durumu: Devlet monad

Ancak, gerçekte kayıtlarını veya hücrelerin mutasyona değiliz, aksine tamamen işlevsel değerini defalarca güncellenmesi, daha basit bir ortam mevcuttur: the State monad. Bu değişebilir duruma izin vermez, ancak yerel durumun bir yanılsamasını verir.

Son olarak

IO ve unsafePerformIO, sen ST monad gibi yerel, değişken etkilere sahiptirler, ama nedense veya başka, sen IO işlemlerini ihtiyacımız olacak eğer durumuna (örneğin Bir FFI çağrısı aracılığıyla), yerel bir IO ortamı oluşturmak için runST yerine unsafePerformIO kullanarak ST monad'ı neredeyse güvenlikle simüle edebilirsiniz. IO monadının soyutlamayı zorlamak için iyi bir türü olmadığı için, yan etkilerin gözlemlenebilir olmayacağından emin olmanız gerekir.

+0

ST monadının bir başka güzel faydası, son derece verimli olmasıdır. Sık sık eşdeğer IO kodundan daha hızlı olmak için ST kodu buldum. –

+0

@John L, aslında IO, bazı ekstra kancalarla ST olarak tanımlanmıştır. –

+0

Don, değişken durum, gözlemci dışındaki fonksiyonlardan tamamen gizlenmiştir. John Launchbury & Simon Peyton'ın Lazy Functional State Threads adlı 1994 tarihli bir çalışmasını okudum. * Bazı algoritmalar, dışsal spesifikasyonları tamamen işlevsel olsa bile, güncellenebilir durumun kritik iç kullanımını sağlar. katı olmayan, tamamen işlevsel bir dil bağlamında çoklu, adlandırılmış, değiştirilebilen nesneleri * işlemek. ST hakkında söylenen kâğıt, ilk defa okuduğumda çok teknikti. Tekrar okuyacağım ve ST monad kullanarak f8, f9 komutunu uygulayacağım. –

5

Bu işlevi FFI kullanarak içe aktardıysanız, yalnızca IO döndürme türünden kaldırın. Else, System.IO.Unsafe'dan unsafePerformIO :: IO a -> a kullanın. Lütfen dikkat, bu fonksiyon Haskell'deki en tehlikeli fonksiyonlardan biridir. Sonuçları etkilemiyorsan, kullanma. Ama amacın için iyi görünüyor.

+6

Muhtemelen, “güvensizPerformNet'in” birkaç “doğru” kullanımından birinin derleyicinin aslında bir işlevin dışsal olarak saf olduğu, bu sorunun tam olarak ne olduğuyla ilgili bir düz iddia olduğunu unutmayın. 'GüvensizPerformIO' 'nun sizi ısırdığı yolların çoğu, bir anlamda sadece "çoğunlukla" saf olan işlevlerde kullanmaktan kaynaklanır. –

+0

Belki de "unsafePerformIO" nun en rahatsız edici yanlış kullanımı, statik arabelleklerin varlığındadır (diş açma güvenli kullanımı değil), bu yüzden çok dikkatli olun! –

+2

@TomMD: Bazen, Haskell programcılarının eğiliminde olduğu kadar "bir şeyler yapmanın" dahil olduğu "yan etkiler" açısından saflıktan bahsetmenin ters faydası olduğunu düşünüyorum. Saf olmayan işlevlerdeki - ve çoğu saf olmayan dillerde - gerçekten sinsi olan hatalar - çoğu zaman dış dünyaya salt okunur erişimi içerenler. –

3

Evet, bu güvenli olmayan bir SecurityPerformIO kullanımı olacaktır. Ancak, görünür bir etki olmadığından eminseniz yalnızca sorun yok.

İlgili konular