SORU
23 Kasım 2012, Cuma


Başka yolları da devlet Monadlar ile yanında saf fonksiyonel bir dil ne olabilir?

Monadlar (Haskell kullanılan) alışmaya başladım. Başka yollar IO veya devlet saf fonksiyonel bir dil (hem teori ya da realite) olarak ele alınabilir ne merak ediyorum. Örneğin, mantıksal bir dil denir "cıva" kullanan "etki-yazma". Haskell gibi bir program, nasıl etkisi-yazarak çalışmak istiyorsunuz? Nasıl Diğer sistemler çalışıyor mu?

CEVAP
24 Kasım 2012, CUMARTESİ


Birkaç farklı sorular var.

İlk, IO State çok farklı şeylerdir. State yapmak kolay kendinizi her fonksiyonu için ekstra bir argüman, ve ekstra bir dönüş sonucu, ve"; örneğin, turn a -> b içine fonksiyon "duruma bir a -> s -> (b,s).

Büyü var no: Control.Monad.State bir sarıcı sağlar "devlet eylemleri" şeklinde s -> (a,s) uygun olarak çalışma yapar yardımcı işlevler, ama bir grup olarak.

O, doğası gereği uygulanmasında bazı büyü var. Ama var kelime içermeyen Haskell G/Ç ifade etmenin pek çok yolu"". monad IO-ücretsiz olarak-Haskell alt ettik, ve IO icat etmek isteseydik çizik, monadlar hakkında hiçbir şey bilmeden, biz belki çok şey var yapın.

Eğer yapmak istediğimiz tüm stdout baskı, örneğin, söyleyebiliriz:

type PrintOnlyIO = String

main :: PrintOnlyIO
main = "Hello world!"

Ve sonra Dize değerlendirir ve yazdıran bir RTS (çalışma sistemi). Bu bizi tamamen baskı meydana gelen herhangi bir Haskell program yazmak sağlar stdout.

Bu etkileşim istediğimiz için çok yararlı, ancak değil! Hadi icat yani bunu sağlayan IO yeni bir tür. Akla gelen en basit şey

type InteractIO = String -> String

main :: InteractIO
main = map toUpper

IO için bu yaklaşım bize standart girdiden okur, herhangi bir kod yazmanıza imkan ve yazar (Başlangıç fonksiyonu interact :: InteractIO -> IO ()ile birlikte gelir stdout bu arada) yapar.

Bu bizi etkileşimli programlar yazmaya olanak sağladığı için çok daha iyi. Ama tek istediğimiz IO kıyasla hala çok sınırlı ve oldukça da hata eğilimli (eğer yanlışlıkla çok ileri stdın okumaya çalışın, program sadece kullanıcı türleri kadar fazla blok).

Daha fazla bilgi edinin daha stdin ve stdout yazmak istiyoruz. Nasıl burada Haskell erken sürümleri/I, yaklaşık:

data Request = PutStrLn String | GetLine | Exit | ...
data Response = Success | Str String | ...
type DialogueIO = [Response] -> [Request]

main :: DialogueIO
main resps1 =
    PutStrLn "what's your name?"
  : GetLine
  : case resps1 of
        Success : Str name : resps2 ->
            PutStrLn ("hi "    name    "!")
          : Exit

main, yazıyoruz biz tembel bir liste değişkeni almak ve tembel bir listesini döndürür sonuç. Biz dönüş tembel listesi PutStrLn s GetLinegibi değerler vardır; biz (istek) bir değer verecek sonra bir sonraki eleman inceleyebiliriz (yanıt) listesi ve RTS bizim cevap için ayarlayacaktır istek.

Bu mekanizma daha iyi çalışma yapmak için yollar vardır, ama düşünün, bu yaklaşım çok garip çok hızlı bir şekilde alır. Ayrıca, hata eğilimli bir önceki ile aynı şekilde.

Burada çok daha az olan bir başka yaklaşım, hata eğilimli ve kavramsal olarak çok nasıl Haskell IO aslında davranır yakın

data ContIO = Exit | PutStrLn String ContIO | GetLine (String -> ContIO) | ...

main :: ContIO
main =
    PutStrLn "what's your name?" $
    GetLine $ \name ->
    PutStrLn ("hi "    name    "!") $
    Exit

Anahtarı "tembel listesi" gibi tepkiler büyük almak yerine bu ana başında argüman, kabul edip, tek tek istekleri yapıyoruz bir anda bir tartışma.

Bizim program şu anda sadece normal bir veri türü bağlı bir liste gibi bir şey dışında ... RTS bazen main, yorumlar sadece normal hareket edemez: bir işlevi, o zaman hadi git tutan GetLine gibi bir değer bulduğu standart girdiden bir dize RTS büyü kullanarak, ve işleve dize geçmek, devam etmeden önce. Egzersiz: interpret :: ContIO -> IO () Yazın.

Bu uygulamaların hiçbiri içeren not "dünya-geçer". "dünya-geçen" Haskell O işleri ben/ne gerçekten değil. Gerçek DZD IO türü uygulama iç bir tür adı içerir RealWorld ama bu uygulama sadece bir detay.

IO ekler gerçek Haskell bir tip eylemler yazabiliriz yani parametre "ürün" rasgele değerler data IO a = Done a | PutStr String (IO a) | GetLine (String -> IO a) | ... daha fazla gibi görünüyor. Bize daha fazla bilgi verir. "keyfi üretmek "IO eylemler yaratabiliriz çünkü esneklik, değerler.

(Russell O'Connor points out, bu tür sadece ücretsiz bir monad. Bunun için Monad bir örneğini kolaylıkla yazabiliriz.)


Nerede monadlar o zaman geliyor? Monad için ihtiyacımız yok çıkıyor G/Ç ve devlet Monad, peki neden ihtiyacımız olsun ki hiç ihtiyacımız yok? Bu cevap vermiyoruz. Hiçbir şey türü Monad sınıfı hakkında büyülü bir şey var.

IO State ile çalışırken ancak, (liste ve fonksiyonları ve Maybe ve devamı-geçen stil ve ...) ayrıştırıcıları yeterince uzun bir süre için, biz sonunda onlar oldukça benzer şekilde bazı şekillerde davranan anlamaya. Olabiliriz listedeki her dize yazdıran bir fonksiyon, ve çalışan bir fonksiyon yazın liste ve bir iş parçacığı her duruma hesaplama devlet ve edecekler birbirine çok benzer.

Benzer görünümlü bir sürü kod yazma gibi olmadığı için bir yol istiyoruz bunu; Monad bize izin verir, çünkü büyük bir soyutlama olur Özet çok farklı görünen birçok çeşit soyut, ama yine de yararlı bir sürü sağlar işlevsellik (Control.Monad herşey dahil).

bindIO :: IO a -> (a -> IO b) -> IO b verilen returnIO :: a -> IO a, monadlar hiç düşünmeden Haskell IO herhangi bir program yazabilir. Ama muhtemelen Control.Monad,bir çok fonksiyonu çoğaltma biter mapM forever when (>=>).

Monad ortak API uygulayarak, aynı kodu kullanıyoruz ayrıştırıcıları ve listeler ile yaptığımız gibi, IO eylemleri ile çalışıyor. Gerçekten tek. benzerlikler yakalamak için Monad sınıf var akıl arasında farklı türleri.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Codecourse

    Codecourse

    3 ŞUBAT 2009
  • Damien Walters

    Damien Walte

    20 AĞUSTOS 2006
  • monkophile

    monkophile

    25 Temmuz 2007