Neden Haskell yan etkileri monadlar olarak modellenmiş?
Herkes Haskell içinde unpure hesaplamaları monadlar olarak modellenmiş neden bazı işaretçiler verebilir misiniz?
Ben monad 4 işlemleri ile sadece bir arayüz demek, modelleme için akıl yan etkileri ne oldu?
CEVAP
Bir işlev yan etkisi yoktur sanırım. Eğer giriş ve çıkış parametreleri olarak üretmek tüm etkileri ele alırsak işlevi dış dünyaya saf.
Saf olmayan bir fonksiyon için
f' :: Int -> Int
göz için Gerçek dünya ekliyoruz
f :: Int -> RealWorld -> (Int, RealWorld)
-- input some states of the whole world,
-- modify the whole world because of the a side effects,
-- then return the new world.
sonra f
saf yine. Biz Gerçek dünya o kadar çok türü gerek yok yani parametrize veri türü IO a = RealWorld -> (a, RealWorld)
tanımlayın
f :: Int -> IO Int
Programcı, doğrudan Gerçek dünya kullanım çok tehlikeli -; eğer bir programcı türü Gerçek değeri ele geçirirse özellikle, alabilirkopyalaesasen imkansız olduğu gibi. (Tüm dosya sistemi taklit etmeye çalışan düşünün, örneğin. Nereye koyardın?) Bu nedenle, IO'NUN bizim tanım olarak bütün dünya devletleri saklar.
Bu saf olmayan işlevleri eğer onları bir araya zincir miyiz diye mi işe yaramaz. Düşünün
getLine :: IO String = RealWorld -> (String, RealWorld)
getContents :: String -> IO String = String -> RealWorld -> (String, RealWorld)
putStrLn :: String -> IO () = String -> RealWorld -> ((), RealWorld)
Bir dosya adı konsolu almak istiyoruz, bu dosya okumak, içeriği yazdırın. Nasıl gerçek dünya devletleri ulaşabilirsek yapardık?
printFile :: RealWorld -> ((), RealWorld)
printFile world0 = let (filename, world1) = getLine world0
(contents, world2) = (getContents filename) world1
in (putStrLn contents) world2 -- results in ((), world3)
Burada bir örüntü görüyoruz: işlevleri şöyle: denir
...
(<result-of-f>, worldY) = f worldX
(<result-of-g>, worldZ) = g <result-of-f> worldY
...
Operatör ~~~
bağlamak için onları tanımlayabiliriz:
(~~~) :: (IO b) -> (b -> IO c) -> IO c
(~~~) :: (RealWorld -> (b, RealWorld))
-> (b -> RealWorld -> (c, RealWorld))
-> RealWorld -> (c, RealWorld)
(f ~~~ g) worldX = let (resF, worldY) = f worldX in
g resF worldY
o zaman sadece yazabiliriz
printFile = getLine ~~~ getContents ~~~ putStrLn
gerçek dünyaya dokunmadan.
Şimdi dosyayı büyük da içerik yapmak istiyorum varsayalım. Uppercasing saf bir fonksiyonudur
upperCase :: String -> String
Ama gerçek dünyaya yapmak, IO String
bir dönüş var. Kolay böyle bir işlevi kaldırmak için:
impureUpperCase :: String -> RealWorld -> (String, RealWorld)
impureUpperCase str world = (upperCase str, world)
bu genelleştirilmiş:
impurify :: a -> IO a
impurify :: a -> RealWorld -> (a, RealWorld)
impurify a world = (a, world)
impureUpperCase = impurify . upperCase
ve yazmak
printUpperCaseFile =
getLine ~~~ getContents ~~~ (impurify . upperCase) ~~~ putStrLn
Şimdi gelelim ne yaptığımıza bakın:
- İki saf olmayan işlevleri birlikte zincirleri 32* *bir operatör tanımladık
- Saf saf bir değeri dönüştüren bir fonksiyon
impurify :: a -> IO a
tanımladık.
Şimdi kimliği (>>=) = (~~~)
** 35, ve biz yapmak? Bir monad var.
(Gerçekten birkaç aksiyom var bir monad olup olmadığını kontrol etmek için tatmin edici olmalıdır:
(1) return a >>= f = f a
impurify a = (\world -> (a, world))
(impurify a ~~~ f) worldX = let (resF, worldY) = (\world -> (a, world)) worldX
in f resF worldY
= let (resF, worldY) = (a, worldX))
in f resF worldY
= f a worldX
(2) f >>= return = f
(f ~~~ impurify) a worldX = let (resF, worldY) = impuify a worldX
in f resF worldY
= let (resF, worldY) = (a, worldX)
in f resF worldY
= f a worldX
(3) f >>= (\x -> g x >>= h) = (f >>= g) >>= h
Egzersiz.)
Neden Haskell (bazen) olarak adlandırı...
Neden &; ad std quot;" kötü olara...
Neden C ön işlemci word "linux&qu...
Neden benim program tam olarak 8192 el...
Neden git ileri varsayılan olarak birl...