Her şeyden önce:
Herhangi bir monad aynı zamanda bir uygulama fonktörüdür ve herhangi bir uygulama fonktörü bir fonktordur.
Bu, Haskell bağlamında doğrudur, ancak ( Applicative
"güçlü gevşek monoidal functor" olarak okumak ) genel olarak değil, farklı monoidal kategoriler arasında "uygulanabilir" functorlara sahip olmanız önemsiz bir nedenden ötürü, monadlar (ve komonadlar) endofunktörlerdir. .
Ayrıca, Applicative
güçlü gevşek monoidal functorlarla tanımlamak biraz yanıltıcıdır, çünkü adın (ve tip imzasının (<*>)
) haklı gösterilmesi, hem monoidal yapıyı hem de dahili homu koruyan kapalı monoidal kategoriler arasında bir functor gerektirir . Bu, her iki özelliği koruyan monoidal kapalı kategoriler arasındaki bir functorun diğerini bariz şekilde koruduğu durumlar dışında buna "gevşek kapalı monoidal functor" denebilir . Çünkü sadece Hask üzerindeki monofonik yapısını koruyan endofunktörleri açıkladığı için , örnekleri , bu şekilde atılabilecek mukavemetleri de dahil olmak üzere otomatik olarak birçok özellik kazanır.Applicative
(,)
Görünen bağlantı Monad
, tartışmasız Applicative
, ilgili monoid yapılarının yönlerinin çakışmasına neden olan örtülü sınırlamaların bir artefaktı, maalesef dualizasyondan sağ çıkamayan mutlu bir tesadüf.
Bir kategorisindeki bir komoderin C o p üzerindeki bir monad olması gibi , bir oplax monoidal functor C → D bir lax monoidal functor C o p → D o p'dir . Ama H a sCCop C→DCop→Dop monoidalkapalıdeğildirvefonksiyon uygulaması içermeyenbirkoliismi pek hak etmez. Her neyse, sonuç çok ilginç olmayacaktı:HaskopApplicative
class (Functor f) => CoMonoidal f where
counit :: f () -> ()
cozip :: f (a, b) -> (f a, f b)
Bunun yerine "kolaks kapalı functor" kavramını hayal edebiliriz, ki bu daha çok Applicative
varmış gibi görünecektir . Ne yazık ki, hiç kapalı bir kategori (benim en iyi bildiğim için) değil: in H a s k karşılık Morfizm için b → bir de H a s k o p , ancak bir olarak çalışmaya değil iç hom orada - oklar tersine çevrildiğinden, bunun yerine genel olarak H a s k için tanımlayamadığımız bir tür işbirliği işlevi gerekecektir .Haskopnewtype Op b a = Op (a -> b)
Haskb→aHaskopOp b a
Hask
için "kolaks kapalı functorlar" ın var olduğunu ve ayrıca saf bir şekilde umduğumuz gibi çalıştığını iddia edersek , buna dayanan bir ortak muhtemelen şöyle görünecektir:HaskApplicative
class (Functor f) => CoApplicative f where
copure :: f a -> a
coap :: (f a -> f b) -> f (a -> b)
Ekleme duplicate :: f a -> f (f a)
için copure
bir comonad üretecektir elbette (kanunlarını varsayarak tatmin edilir). Ancak - ne coap
olursa olsun - ve arasında açık bir ilişki yoktur extend :: (f a -> b) -> f a -> f b
. Tiplerin karşılaştırılması, dualizasyonun farklı şekillerde gerçekleştiği açıktır: altta yatan duplicate
ve cozip
birbirleriyle veya birbirleriyle coap
(muhtemelen hiçbir şekilde anlam ifade etmemektedir) olan liftA2 (,)
ve (<*>)
bunlarla eşdeğer olan ve türetilebilen ortak yapıların çok az olduğu açıktır join
.
Komonadlarla Applicative
daha da az ilgisi olan bir çiftleştirmenin olası başka bir yolu, kontravaryant monoidal fonksiyonları düşünmektir:
class (Contravariant f) => ContraMonoidal f where
contraunit :: f a
contrazip :: f a -> f b -> f (Either a b)
Haskopb <~ a
contracurry :: (Either c b <~ a) -> (c <~ (b <~ a))
contraapply :: b -> Either a (a <~ b)
Eğer hafıza bana hizmet ederse, buradaki engeller Haskell'e özgü değildir, daha çok 'Ha s kKartezyen kapalı olmak (her zamanki el sallamalarına kadar), en çok yazılan lambda calculi ile paylaştığı bir özelliktir, bu yüzden CoApplicative
çoğu ayarda çok uzaklara gitme olasılığınız yoktur .
Bununla birlikte, dualizasyon için daha misafirperver olan monoidal kapalı bir kategoride daha iyi şansınız olabilir. Özellikle, her ikisinin Kleisli (Cont r)
ve zıt kategorisinin monoidal kapalı olduğuna inanıyorum , bu yüzden bu fikirleri keşfetmek için daha iyi bir bağlam olabilir.