SORU
19 EKİM 2012, Cuma


Monad fonksiyonları için Transformers vs Geçen parametreleri

Haskell ama Monad Transformers nasıl kullanılabileceğini anlamak için yeni duyuyorum. Ama ben yine de zorluklar işlev çağrıları için parametreleri üzerinden geçen iddia avantajı kapma.

Wiki dayalı Monad Transformers Explained, temelde kusurlu bir Nesne olarak tanımlamış

data Config = Config Foo Bar Baz

ve onu geçmek, bu imza ile işlevleri yazmak yerine

client_func :: Config -> IO ()

ReaderT bir Monad Transformer kullanıyoruz ve imza değiştirin

client_func :: ReaderT Config IO ()

Config çekerek sonra 12 ** sadece bir çağrı.

İşlevi runReaderT client_func c 13 *değişiklikleri arayın

Güzel.

Ama neden bu benim uygulama daha basit yapar mı ?

1 - Monad Transformers birlikte bir başvuru formu için modüller/fonksiyonlar bir sürü dikiş atarken bir ilgi var sanırım. Ama bu anlama benim durur. Biri bizi aydınlatabilir misiniz?

2 - bir büyük yazmak nasıl herhangi bir belge bulamadımmodülernerede Haskell modüllerinde uygulama ve uygulamaları API gizlemek gibi (kısmen) diğer modüllerden kendi Devletleri ve çevrelerinden gizlemek çeşit göstermek. Herhangi bir işaretçiler lütfen ?

(Edit: Real World Haskell Birleşik Devletleri ".. bu yaklaşım bir Monad Transformers] ... daha büyük programları destekliyor." ama net bir örneği olduğunu iddia) gösteren yok

Aşağıdaki Chris Taylor Altına Cevap yazınız

Chris mükemmel Config, Devlet,vb şifrelenmiş açıklıyor... Trafo bir Monad içinde iki fayda sağlar:

  1. Önler daha yüksek seviyede işlev olması için bakımını kendi türüne imza tüm gerekli parametreleri tarafından (alt)işlevleri çağırır ama gerekmediği için kendi kullan (getUserInput fonksiyon)
  2. ve sonuç olarak yapar yüksek seviye fonksiyonlar daha esnek bir değişimin içeriği Trafo Monad (diyelim ki eklemek istediğiniz bir Writer bunu sağlamak için giriş düşük seviyeli fonksiyon)

Bu yüzden tüm fonksiyonları imza değiştirme pahasına birlikte kaçıyorlar "" Trafo Monad.

Yani 1 soru tamamen kaplıdır. Chris teşekkür ederim.

Soru 2 this SO post cevaplanır

CEVAP
19 EKİM 2012, Cuma


Hadi şu biçimde bazı yapılandırma bilgilerini gereken bir program yazıyoruz ki:

data Config = C { logFile :: FileName }

Program yazmak için bir yolu açıkça yapılandırma etrafında işlevleri arasında geçiş için. O-cekti var olmak güzel eğer biz sadece geçmek için fonksiyonları kullanımı açıkça, ama ne yazık ki emin değiliz, bir işlevi olabilir aramalısınız, başka bir işlevi kullanan yapılandırma, yani zorla geçmek gibi bir parametre her yerde (aslında, bu eğilimi olması düşük seviye işlevleri kullanmaya ihtiyaç yapılandırma, hangi güçler bize geçmek için tüm üst düzey fonksiyonları gibi).

Böyle program yazalım, sonra yeniden yazmak Reader monad kullanarak ve bakalım ne olacak.

Seçenek 1. Açık yapılandırma geçiyor

Bunun gibi bir şey ile bitireceğiz:

readLog :: Config -> IO String
readLog (C logFile) = readFile logFile

writeLog :: Config -> String -> IO ()
writeLog (C logFile) message = do x <- readFile logFile
                                  writeFile logFile $ x    message

getUserInput :: Config -> IO String
getUserInput config = do input <- getLine
                         writeLog config $ "Input: "    input
                         return input

runProgram :: Config -> IO ()
runProgram config = do input <- getUserInput config
                       putStrLn $ "You wrote: "    input

Yüksek düzey pointer fonksiyonları her zaman etrafında config dikkat edin.

Seçenek 2. Okuyucu monad

Alternatif Reader monad kullanarak yeniden yazmak için. Bu düşük seviyeli fonksiyonları biraz karıştırıyor:

type Program = ReaderT Config IO

readLog :: Program String
readLog = do C logFile <- ask
             readFile logFile

writeLog :: String -> Program ()
writeLog message = do C logFile <- ask
                      x <- readFile logFile
                      writeFile logFile $ x    message

Ama bizim ödül olarak, yüksek seviyeli işlevler biz asla yapılandırma dosyasına başvurmak gerekir, çünkü daha kolaydır.

getUserInput :: Program String
getUserInput = do input <- getLine
                  writeLog $ "Input: "    input
                  return input

runProgram :: Program ()
runProgram = do input <- getUserInput
                putStrLn $ "You wrote: "    input

Daha da alma

Yeniden yazmak getUserİnput ve runProgram tür imzalar olmamız olabilir

getUserInput :: (MonadReader Config m, MonadIO m) => m String

runProgram :: (MonadReader Config m, MonadIO m) => m ()

bize eğer herhangi bir nedenle Program temel türünü değiştirmek istediğimize karar verirsek daha sonra, esneklik çok verir. Eğer programımız için değiştirilebilir devlet eklemek istiyorsak örneğin, yeniden yapabiliriz

data ProgramState = PS Int Int Int

type Program a = StateT ProgramState (ReaderT Config IO) a

getUserInput runProgram değiştirmek zorunda değiliz. - iyi çalışmaya devam edecekler.

N. B. ben yazın Bu yazıya bakmadım, bırak kaçmayı denedi. Hatalar olabilir!

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • eurotuner

    eurotuner

    6 Mart 2006
  • TheTwistedFrequency

    TheTwistedFr

    26 NİSAN 2010
  • tinycammonitor

    tinycammonit

    14 Aralık 2010