SORU
1 Mayıs 2010, CUMARTESİ


Fonksiyonel programlama dilleri nasıl çalışır?

Eğer fonksiyonel programlama dilleri herhangi bir devlet tasarrufu olamaz, nasıl bir kullanıcı giriş okuma gibi basit şeyler yapıyorlar? Nasıl "" giriş (ya da bu konuda herhangi bir veri depolamak?) saklıyorlar

Örneğin: nasıl bu basit C şey Haskell gibi fonksiyonel bir programlama dili çevirmek istiyorsunuz?

#include<stdio.h>
int main() {
    int no;
    scanf("%d",&no);
    return 0;
}

(Benim sorum bu mükemmel yazıya ilham kaynağı oldu: "Execution in the Kingdom of Nouns". Bana nesne tabanlı programlama ne daha iyi bir anlayış verdi okuma, Java nasıl aşırı bir şekilde uygular ve nasıl fonksiyonel programlama dilleri bir kontrast.)

CEVAP
1 Mayıs 2010, CUMARTESİ


Eğer fonksiyonel programlama dilleri kaydedemiyor herhangi bir devlet, nasıl yapıyorlar bazı basit şeyler gibi okumaya giriş bir kullanıcı (yani nasıl "mağaza"), ya da herhangi bir veri depolamak için fark eder mi?

Siz toplandıkça, işlevsel programlama-devlet yok;ama bu veriyi depolayabilir anlamına gelmez. Fark eğer yazarsam bir (Haskell) çizgisinde deyim

let x = func value 3.14 20 "random"
in ...

x değeri her zaman ... aynı olduğunu garanti ediyorum: hiçbir şey bunu değiştiremez. Benzer şekilde, eğer bir fonksiyon f :: String -> Integer (bir fonksiyonu alarak bir dize ve bir tamsayı döndüren), olabilirim emin f olmaz değiştir argüman veya değiştirmek herhangi bir global değişkenler veya veri yazmak için bir dosya, ve benzeri. Olarak sepp2k söyledi bir yorum yukarıda, bu non-mutability gerçekten yararlı için mantık hakkında programlar: yazdığınız fonksiyonları olan pas, mil, ve sakat verilerinizi dönen yeni kopyalarını böylece zincir onları bir araya, ve emin ol hiç biri işlev çağrıları yapabiliriz "zararlı". Bildiğiniz x her zaman x ve sen endişelenme biri yazdı x := foo bar ikisinin arası Bildirgesi x ve kullanımı, çünkü bu imkansız.

Şimdi, Eğer bir kullanıcı giriş okumak için ne yapmalıyım? KennyTM dediği gibi, fikri kirli bir işlev bağımsız değişken olarak tüm dünyaya geçti ve sonuç, hem de dünya döndüren saf bir fonksiyonu olmasıdır. Tabii ki, aslında bunu yapmak istemezsin: bir kere, hantal, korkunç, ve başka bir şey, eğer ben yeniden ne olur aynı dünya nesne? Bu soyutlanmış bir şekilde alır. Haskell IO tür işleme:

main :: IO ()
main = do str <- getLine
          let no = fst . head $ reads str :: Integer
          ...

Bu main hiçbir şey verir IO bir eylem olduğunu söyler; bu eylemi yürütmek Haskell bir programı çalıştırmak için ne anlama geldiğini. Kural IO IO tür hiç bir eylem kaçabilir; bu bağlamda, biz bu eylemi do kullanarak tanıtmak. Böylece, getLine döndürür IO String, düşünce iki yolu vardır: ilk olarak bir eylem ki, ne zaman çalışacak, üreten bir dize; ikinci olarak, bir dize olarak bu "kusurlu" tarafından IO beri elde edilmiş impurely. Birincisi daha doğrudur, ama ikinci daha faydalı olabilir. <- gereken String out IO String mağazalar str - ama bu yana olduğumuzu bir IO eylem yapmamız gerekiyor sarın geriye, yani "kaçış". Sonraki satırı okumaya kalkışır bir tamsayı (reads) ve kapmak başarılı ilk maç (fst . head); bu saf (IO), bu yüzden biz bir isim verin let no = .... Sonra no ... str Her ikisi de kullanabiliriz. Böylece kirli veri (str içine getLine) ve saf verileri (let no = ...) saklı ettik.

IO ile çalışan çok güçlü olduğu için bu mekanizma: sağlar, kirli, kullanıcı etkileşimi yan, programın saf, algoritmik kısmı ayrı ve tür düzeyinde uygulanması. minimumSpanningTree fonksiyon muhtemelen bir şey kodunuzda başka bir yerde değiştirebilir mi, ya da kullanıcı için bir mesaj yazın. Güvenli.

Bu Haskell IO kullanmak için bilmeniz gereken, eğer istediğin buysa, burada durabilirsiniz. Ama eğer anlamak istiyorsanıznedeno, okumaya devam et çalışır. (Ve bu şeyler Haskell-özel olacaktır;diğer dillerden farklı bir uygulama seçmek unutmayın.)

Yani bu muhtemelen biraz hile gibi, bir şekilde saf Haskell için kirlilik ekleme görünüyordu. Ama mi-değil;IO türü tamamen saf Haskell (RealWorld vermiş olduğumuz sürece) içinde uygulamaya koyabiliriz ortaya çıktı. Fikir şu: bir eylem IO IO type aynı fonksiyonu RealWorld -> (type, RealWorld) sürer) gerçek dünya ve verir, hem de bir nesnenin türü type modifiye RealWorld. Biz deli gitmeden bu tür kullanabiliriz o zaman birkaç fonksiyonları tanımlayın:

return :: a -> IO a
return a = \rw -> (a,rw)

(>>=) :: IO a -> (a -> IO b) -> IO b
ioa >>= fn = \rw -> let (a,rw') = ioa rw in fn a rw'

Birincisi bize bir şey yapmadığım halde IO eylemler hakkında konuşmak için izin verir: return 3 gerçek dünya ve sadece döner 3. sorgu yok IO bir eylemdir >>= operatör, telaffuz "" bizi IO eylemleri çalıştırmak için izin verir. bağlama IO eylem değeri ayıklar, işlevi yoluyla ve gerçek dünyaya geçer, ve elde edilen IO eylem verir. >>= IO sonuçlarını asla kaçmalarına izin kurallarımız gereği zorlar unutmayın.

Sonra fonksiyon uygulamaları aşağıdaki sıradan sete main yukarıdaki çevirebiliriz:

main = getLine >>= \str -> let no = (fst . head $ reads str :: Integer) in ...

Haskell çalışma zamanı sıçrama başlar RealWorld ve hazır başlangıç main! Her şey saf, öyle havalı bir sözdizimi vardır.

[Düzenleme:58 ** bu Haskell IO yapmak için kullandığı aslında değil. Bu model Haskell bu modeli kullanmak imkansız olurdu eğer öyleyse eşzamanlılık eklerseniz, ya da aslında dünya için herhangi bir şekilde değiştirmek için IO eylem ortasında keser. Sıralı hesaplama için sadece doğru. Böylece, Haskell IO bir dodge biraz; eğer doğru değilse, kesinlikle bu şık değil, değil mi bu bile olabilir. Başına @Conal gözlem, bakın ne Simon Peyton-Jones diyor ki Tackling the Awkward Squad [pdf] bölüm 3.1; o hediye ne olabilir miktar için alternatif bir model bu doğrultuda, ama sonra düşer bunun için karmaşıklığı alır ve farklı bir çakmak.]

Yine, bu IO, ve genel olarak mutability, Haskell nasıl çalıştığını ve çok güzel bir çok şeyi açıklıyor; eğerbubilmek istediğiniz tüm, okumayı burada bırakabilirsiniz. Teorinin son bir doz istiyorsanız, okuma-devam et, ama unutma, bu noktada, şu soru çok uzaklara gittik!

Bu yüzden son bir şey: anlaşılan bu yapı-parametrik tip return >>= - çok genel; deniyor monad, ve do gösterim, return >>= iş ile herhangi biri. Burada gördüğünüz gibi, monadlar büyülü değil; sihirli, hepsi do blok işlev çağrıları dönüştüğü. RealWorld tür sihir gördüğümüz tek yer. [], liste oluşturucu, gibi türleri de monadlar ve saf olmayan kod ile alakaları yok.

Şimdi (neredeyse) bir monad (yerine getirilmesi gereken birkaç yasa ve resmi matematiksel tanımını hariç) kavramı hakkında her şeyi biliyorum, ama sezgi eksikliği. Monad öğreticiler online saçma bir dizi var; this one severim ama seçenekler var. Ancak, this probably won't help you; sezgi elde etmek için tek gerçek yolu, onları kullanarak bir kombinasyonu ile bir çift okuma ve doğru zamanda öğreticiler.

Ancakbu sezgi IO anlamana gerek yok. Tam olarak anlamak monadlar genellik kek üzerine krema, ama IO anda kullanabilirsiniz. main ilk işlevi gösterdim sonra kullanabilirsin. Hatta saf olmayan bir dilde, sanki IO kodu davranabilirsiniz! Ancak temel işlevsel bir temsil olduğunu unutmayın: kimse hile.

(PS: uzunluğu için Kusura bakma Biraz uzaklara gittim.)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Lena Danya

    Lena Danya

    11 NİSAN 2010
  • TheFlashCentre

    TheFlashCent

    22 Mayıs 2008
  • Tinkernut

    Tinkernut

    28 Aralık 2006