2014-11-28 16 views
11

Merhaba Zavallı Adamın Eşzamanlı Monad'ını uygulamaya çalışıyorum. f(a -> ((b ->Action) -> Action)) türünü sahiptir ya tipini sahiptir xb tipini vardır: İşte >> = Kötü Adamın Eşzamanlılığı Monad için uygulama

import Control.Monad 

data Concurrent a = Concurrent ((a -> Action) -> Action) 

data Action 
    = Atom (IO Action) 
    | Fork Action Action 
    | Stop 

instance Monad Concurrent where 
    (Concurrent ma) >>= f = Concurrent (\x -> ma(\y -> "Something return a Action")) 
    return x = Concurrent (\c -> c x) 

benim analizidir: İşte benim kodudur. "Bir eyleme Geri Döndür" i anlayabilmek için ilk olarak ((b ->Action) -> Action) türünü döndüren (f y) değerini hesaplıyorum. Daha sonra, bir Eylem oluşturmak için x ile nasıl kullanabilirsiniz?

+0

Analizleriniz yanlış. 'x'' b -> Action' türüne sahiptir, 'b' değil. – bennofs

+0

[Free Monad] 'a göz atmak isteyebilirsiniz (http://stackoverflow.com/questions/13352205/what-are-free-monads). Rasgele tekrar edilebilen bir monad kaydetmenize izin verir. Hafif iplikler için kullandım. – Franky

cevap

21

Aradığınız tanım okur biz oraya nasıl oldu

Concurrent h >>= k = Concurrent (\f -> h (\x -> runConcurrent (k x) f)) 

gibi bir şey? Her zaman olduğu gibi, türlerin işi yapmasına izin veriyoruz. , Sonra hedeftir sen h :: (a -> Action) -> Action ve k :: a -> Concurrent b ile tanımına

Concurrent h >>= k = ... 

sol tarafı ile başlarsanız

runConcurrent     :: Concurrent b -> (b -> Action) -> Action 
runConcurrent (Concurrent h) = h 

: :)

bize ilk bir yardımcı işlevi tanıştırayım ...'u Concurrent b türünde bir ifadeyle değiştirmek için değil mi?

Concurrent b türünde bir değeri nasıl oluşturabiliriz? Bir yol k işlevimizi uygulamaktır, ancak bu çalışmaz, çünkü argüman olarak kullanılabilir a türünde uygun bir değere sahip değiliz. Yani, yapabileceğimiz tek şey, ((b -> Action) -> Action) -> Concurrent b tipindeki Concurrent veri yapısını uygulamaktır.

verir Yani:

Concurrent h >>= k = Concurrent ... 

Şimdi gidip bize Concurrent için bir argüman olarak tedarik tip (b -> Action) -> Action bir ifadeyi bulmak zorundayız. Biz fonksiyonu Çeşidi ifadeler her zaman lambda-soyutlama yoluyla inşa edilebileceğini biliyoruz:

Concurrent h >>= k = Concurrent (\f -> ...) 

Bu bize tip Action bir anlatımda ile ... yerine f :: b -> Action ve yükümlülüğünü verir. Action -şarktörlerinden birini doğrudan kullanmak elbette hile yapar;). (>>=) (daha kesin olarak, monad yasalarına uymak zorunda olduğumuzdan emin olmak için) jenerikliğini garanti etmek için, Action, soyut bir veri türü gibi davranırız. Bir sonraki biz tip a -> Action bir argümanla h sağlamanız gerekmektedir, Bu nedenle

Concurrent h >>= k = Concurrent (\f -> h ...) 

: Sonra, bir Action -Değer üretmek için tek yol fonksiyonunu h uygulamaktır. Bir daha bir fonksiyon tipi, bu nedenle başka bir lambda atmak:

Concurrent h >>= k = Concurrent (\f -> h (\x -> ...)) 

Dolayısıyla, x :: a ve tip Action bir gövde oluşturmak gerekir. a türünde bir değerle neler yapabiliriz?Bunu k işlevine sağlayabiliriz. Bu bize daha sonra bizim yardımcı işlevi runConcurrent için geçebilir tip Concurrent b, değerini verir:

Concurrent h >>= k = Concurrent (\f -> h (\x -> runConcurrent (k x) ...)) 

Bu hile bize tip (b -> Action) -> Action bir işlev verir ve bağımsız değişken olarak f tedarik yapar:

Concurrent h >>= k = Concurrent (\f -> h (\x -> runConcurrent (k x) f)) 
+0

Çalışıyor. Çok teşekkür ederim!! –

+0

Veri yapıcısı 'Concurrent' küçük hata türü' ((b -> Eylem) -> Eylem) -> Eşzamanlı b' değil '((b -> Eylem) -> b) -> Eşzamanlı b'. Ben haklı mıyım – fdelsert

+0

@fdelsert Kesinlikle haklısınız. Onu gördüğünüz için teşekkürler. Cevapta düzeltildi. –

İlgili konular