* -> *
türlerinin hangi tür "oluşturabileceğini" içeren çeşitli kavramlar vardır. Daha önemli olan, onları "sıralı olarak" oluşturabilmenizdir.
newtype Compose f g x = Compose { getCompose :: f (g x) }
Burada Compose
tür (* -> *) -> (* -> *) -> (* -> *)
çok functors herhangi iyi kompozisyon gibi sahip olduğunu görmelisin yapabilirsiniz.
Yani soru şu: Aşağıdaki gibi yasalara uyan durumlar vardır?
instance (Applicative f, Applicative g) => Applicative (Compose f g)
instance (Monad f, Monad g) => Monad (Compose f g)
Ve monads yanı applicatives olarak oluşturmak yok neden olarak kısa cevap ilk derece ikinci yazılabilir kullanımın oldukça olamaz olduğunu. Hadi deneyelim!
Biz Functor
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose fgx) = Compose (fmap (fmap f) fgx)
ile ısınabilirler Burada elimizden fmap
bir fmap
f
-ed çünkü biz gerekiyor gibi biz katmanları f
ve g
içinden geçebilir görüyoruz. Benzer bir oyun pure
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure a = Compose (pure (pure a))
ile oynanan ve (<*>)
yaparken dikkatli bakarsan biz fmap
ve pure
ikisi ile kullanılan aynı numara, zor görünür. umut edebileceğiniz gibi
Compose fgf <*> Compose fgx = Compose ((<*>) <$> fgf <*> fgx)
Her durumda, biz tam olarak f
ve g
katmanları "yoluyla" İhtiyacımız operatörleri zorlayabilir.
Ama şimdi en Monad
bir göz atalım. Monad
'u (>>=)
aracılığıyla tanımlamaya çalışmak yerine join
aracılığıyla çalışacağım.Monad
uygulamak için biz newtype
gürültü kapalı şerit halinde olduğumuzu net olabilir Bu noktada
join :: f (g (f (g x))) -> f (g x)
ihtiyaç
join_f :: f (f x) -> f x -- and
join_g :: g (g x) -> g x
kullanılarak
join :: Compose f g (Compose f g x) -> Compose f g x
uygulamak gerekir ya da ne problem --- biz sadece s veya g
s katmanlarınakatmanın nasıl katılacağını biliyoruz ama burada arası interwoven'i görüyoruz. Ne bulacaksınız biz Yerdeğiştirme özelliği
class Commute f g where
commute :: g (f x) -> f (g x)
ihtiyaç ve şimdi
join :: f (g (f (g x))) -> f (g x)
join fgfgx = fgx where
ffggx :: f (f (g (g x)))
ffggx = fmap commute fgfgx
fggx :: f (g (g x))
fggx = join_f ffggx
fgx :: f (g x)
fgx = fmap join_g fggx
olarak tanımlanan (agnostik
newtype
)
join
ile
instance (Monad f, Monad g, Commute f g) => Monad (Compose f g)
uygulamak olmasıdır
Peki, bütün bunlar ne anlama geliyor? s her zamanCompose
, ancaks Compose
yalnızca katmanları Commute
olduğunda.
commute
katmanları ne zaman yapabiliriz? Burada tüm bu demektir olduğuna inanıyoruz, bu yana
instance Commute ((->) x) ((->) y) where
commute = flip
instance Commute ((,) x) ((,) y) where
commute (y, (x, a)) = (x, (y, a))
instance Commute ((->) x) ((,) y) where
commute (y, xa) = \x -> (y, xa x)
-- instance Commute ((,) x) ((->) y) does not exist; try to write yourself!
--
-- OR:
-- It turns out that you need to somehow "travel back in time" to make it
-- work...
--
-- instance Commute ((,) x) ((->) y) where
-- commute yxa = (..., \y -> let (x, a) = yxa y in a)
"Monad Dönüştürücüler" bölümünde bazı örnekler (Uygulamalı f Uygulamalı g) => 'bu Uygulamalı (Cı-fg)' ancak durum böyle bu '(Monad f, Monad g) => Monad (C fg)', burada veri C fga = C (f (ga)) 'dir. Durumun neden böyle olduğuna dair daha derin bir anlayış istiyorsanız, ikinci örneği yazmayı deneyebilirsiniz. – user2407038
Ayrıca bakınız [Mantarlar kompozisyon altında kapalı (prova ile) kapalı olmadığını gösteren somut örnek?] (Http://stackoverflow.com/q/13034229/1333025) –