2011-06-11 17 views

cevap

1

Özel değiştiriciler ve girişler ile birlikte bir State monad ile birlikte olabilir?

+0

, bana da 'State' monadın özel bir kullanım benziyor. –

-3

Durum deseni için tamamen işlevsel bir eşdeğer olduğunu sanmıyorum. Çünkü saf fonksiyonel programlama, devlet ve zaman kavramına sahip değildir. Devlet kalıbı içsel olarak devlet ve zaman ile ilgilidir. Ama ben saf olmayan fonksiyonel eşdeğer var olduğunu düşünüyorum, sonsuz tembel değerlendirilmiş akışı. Bunu C# verimi ile uygulayabilirsiniz.

+1

FP gerçekten de durumu var. Monadları hiç duymadım mı? Zamanla değişen durumu yakalamak için işlevsel reaktif programlama denen bir şey bile var. – fuz

+0

notu "saf" ve "saf olmayan" sözcüklerini kullandım. – Dagang

+1

"İşlevsel programlama" ve "durum" u bağlamak için doğru kelime olduğunu düşünmüyorum. Bunu "modeller" olarak düşünmeyi seviyorum - devletin ne anlama geldiği konusunda işlevsel bir model oluşturarak durumsal hesaplamalar yapabiliriz. – luqui

7

Bu kalıp, bir ortamının durum koduyla kodlandığı State monad kullanımının bir örneğidir.

İşte Haskell'de bir uygulama.

Bazı yardımcıları: Programın

data Mode = A | B 

bir sayaç artar bu modu ile durum bilgisi hesaplamaları, tipi işleyişinin

import Control.Monad.Trans.State 
import Control.Monad.IO.Class 
import Data.Char 

iki mod. devlet bir

başlangıçta bir durum bilgisi hesaplama başlatılması,

writeName :: String -> StateM() 
writeName s = do 
    (n,mode) <- get 
    case mode of 
     A -> do liftIO (putStrLn (map toLower s)) 
       put (0,B) 
     B -> do let n' = n + 1 
       liftIO (putStrLn (map toUpper s)) 
       if n' > 1 then put (n', A) 
          else put (n', B) 

çalıştırın programı:

type StateM a = StateT (Int, Mode) IO a 

yazma fonksiyonu, tabloların bağlamında bir fonksiyon, durum bilgisi moduna göre davranışını değiştirir

main = flip runStateT (0, A) $ do 
    writeName "Monday" 
    writeName "Tuesday" 
    writeName "Wednesday" 
    writeName "Thursday" 
    writeName "Saturday" 
    writeName "Sunday" 

Yukarıdaki koddan, ana çıktı şu şekildedir:

monday 
TUESDAY 
WEDNESDAY 
thursday 
SATURDAY 
SUNDAY 

Bunun tamamen işlevsel bir çözüm olduğunu unutmayın. Bu programda değişebilir veya yıkıcı güncellemeler yoktur. Bunun yerine, durum monadı, hesaplama yoluyla istenen modu işar.

+1

Bunun sadık bir kodlama olduğunu söyleyemem: Burada tüm modları tek bir yerde ('Veri Modu') ilan etmeliyiz, oysa wikipedia örneğinde bildirimler modüler olarak birleştirilebilir. – luqui

+0

ML tarzı dillerdeki kapalı veri türlerine standart çeviri budur. Açıkçası, açık veri tiplerini fonksiyonlar veya tip sınıfları aracılığıyla kullanmaya başlayabiliriz, ancak bu problemle alakalı olmadığını düşünüyorum. –

+1

Standart bir çeviri olduğunu ve standart olarak ne demek istediğini merak ediyorum. – luqui

5

Bir kodlama:

import Data.Char (toUpper, toLower) 

newtype State = State { unState :: String -> IO State } 

stateA :: State 
stateA = State $ \name -> do 
    putStrLn (map toLower name) 
    return stateB 

stateB :: State 
stateB = go 2 
    where 
    go 0 = stateA 
    go n = State $ \name -> do 
       putStrLn (map toUpper name) 
       return $ go (n-1) 

IO tarafından aldanmayın, bu o modelin saf çevirisidir (biz devlet ya da bir şey saklamak için bir IORef kullanmıyorsanız). newtype genişletilmesi, biz bu türünün ne anlama geldiğini bakın: vb,

State = String -> IO (String -> IO (String -> IO (String -> ... 

Bir dize alır bazı G/Ç yapar ve başka bir dize sorar

Bu soyut sınıf desen benim favori kodlama içindedir OO: soyut sınıf -> tür, alt sınıflar -> bu türden elemanlar.

newtype State beyanı, writeName bildirgesinin ve imzasının yerini alır. Yeni bir eyalet atadığımız bir StateContext'u geçmek yerine, yeni durumu iade ediyoruz.Dönüş değerinin IO'a gömülmesi, yeni durumun G/Ç'ye bağlı olmasına izin verildiğini belirtir. bu örnekte teknik olarak gerekli olmadığı için, biz yine de bu hesaplamayı ifade hangi daha sıkı tip

newtype State = State { unState :: String -> (State, IO()) } 

kullanabilir, ancak durumlarının dizisi sabit ve giriş bağlıdır izin değildir. Ama orijinal, daha yumuşak tipine sadık olalım.

Ve "test istemcisi" için

: Kabul

runState :: State -> [String] -> IO() 
runState s [] = return() 
runState s (x:xs) = do 
    s' <- unState s x 
    runState s' xs 

testClientState :: IO() 
testClientState = runState stateA 
        [ "Monday" 
        , "Tuesday" 
        , "Wednesday" 
        , "Thursday" 
        , "Saturday" 
        , "Sunday" ] 
+0

P.S. Sayaç değiştirme semantiklerini de yakalamanız gerekir. –

+0

@Don, oh, doğru. hmm .... – luqui

+0

Değeri için, bu kodlama tarzının sadece soyutlanmış davranışları içine alan gerçek OO-idiomatik sınıflar için ideal olduğunu söyleyebilirim. İddiaya göre OO kodunda yer alan "sınıflar" ın baskıcı bir sayısı, kullanılan Don tarzının hantal tercümelerine çok daha yakındır ve bu nedenle ilk başta olmak istedikleri şeye geri dönmekten faydalanır. –