ApplicativeTypeclass temsil gevşek monoidal fanktorlar o yazdığınız fonksiyonları kategorisine kartezyen monoidal yapısını korumak.
Başka bir deyişle, (,)monoidal bir yapı oluşturan tanık kanonik izomorfizmlere bakıldığında :
-- Implementations left to the motivated reader
assoc_fwd :: ((a, b), c) -> (a, (b, c))
assoc_bwd :: (a, (b, c)) -> ((a, b), c)
lunit_fwd :: ((), a) -> a
lunit_bwd :: a -> ((), a)
runit_fwd :: (a, ()) -> a
runit_bwd :: a -> (a, ())
Typeclass ve yasaları aynı şekilde şu şekilde yazılabilir:
class Functor f => Applicative f
where
zip :: (f a, f b) -> f (a, b)
husk :: () -> f ()
-- Laws:
-- assoc_fwd >>> bimap id zip >>> zip
-- =
-- bimap zip id >>> zip >>> fmap assoc_fwd
-- lunit_fwd
-- =
-- bimap husk id >>> zip >>> fmap lunit_fwd
-- runit_fwd
-- =
-- bimap id husk >>> zip >>> fmap runit_fwd
Aynı yapıya göre oplax monoidal olan bir functor'un nasıl görünebileceği merak edilebilir :
class Functor f => OpApplicative f
where
unzip :: f (a, b) -> (f a, f b)
unhusk :: f () -> ()
-- Laws:
-- assoc_bwd <<< bimap id unzip <<< unzip
-- =
-- bimap unzip id <<< unzip <<< fmap assoc_bwd
-- lunit_bwd
-- =
-- bimap unhusk id <<< unzip <<< fmap lunit_bwd
-- runit_bwd
-- =
-- bimap id unhusk <<< unzip <<< fmap runit_bwd
Tanımlara ve yasalara dahil olan türleri düşünürsek, hayal kırıklığı yaratan gerçek ortaya çıkar; OpApplicativeaşağıdakilerden daha belirgin bir kısıtlama değildir Functor:
instance Functor f => OpApplicative f
where
unzip fab = (fst <$> fab, snd <$> fab)
unhusk = const ()
Bununla birlikte, her Applicativeişlev (gerçekten, herhangi bir Functor) önemsiz OpApplicativeolsa da, Applicativegevşeklik ve OpApplicativeoplaksite arasında mutlaka güzel bir ilişki yoktur. Böylece kartezyen monoidal yapı ile güçlü monoidal functorlar arayabiliriz :
class (Applicative f, OpApplicative f) => StrongApplicative f
-- Laws:
-- unhusk . husk = id
-- husk . unhusk = id
-- zip . unzip = id
-- unzip . zip = id
Yukarıdaki ilk yasa önemsizdir, çünkü türün tek sakini () -> ()kimlik işlevidir ().
Ancak, geri kalan üç yasa ve dolayısıyla alt sınıfın kendisi önemsiz değildir . Özellikle, her Applicativebiri bu sınıfın yasal bir örneği değildir .
İşte Applicativeyasal örneklerini beyan edebileceğimiz bazı işlevler StrongApplicative:
IdentityVoidF(->) r(cevaplara bakınız)Monoid m => (,) mVec (n :: Nat)Stream(sonsuz)
Ve işte Applicativeyapamayacağımız bazı s:
[]Either eMaybeNonEmptyList
Buradaki desen, StrongApplicativesınıfın bir anlamda FixedSizesınıf olduğunu gösterir, burada "sabit boyut" * , bir sakinte yaşayanların çokluğunun ** sabit olduğu anlamına gelir .af a
Bu iki varsayım olarak ifade edilebilir:
ApplicativeKendi tür argümanındaki öğelerin "sabit boyutlu" bir kabını temsil eden her biri,StrongApplicativeStrongApplicativeOluşma sayısınınadeğişebileceği hiçbir örnek yoktur.
Herkes bu varsayımları çürüten karşı örnekleri ya da neden doğru ya da yanlış olduklarını gösteren ikna edici bir akıl yürütmeyi düşünebilir mi?
* "Sabit boyut" sıfatını doğru tanımlamamışım. Ne yazık ki görev biraz dairesel. "Sabit boyutlu" bir konteynerin herhangi bir resmi tanımını bilmiyorum ve bir tane bulmaya çalışıyorum. StrongApplicativeşimdiye kadarki en iyi girişimim.
Bununla birlikte, bunun iyi bir tanım olup olmadığını değerlendirmek için, karşılaştırılacak bir şeye ihtiyacım var. Bir işlevin, tür argümanında yaşayanlara göre belirli bir boyuta veya çokluğa sahip olmasının ne anlama geldiğine dair bazı resmi / gayri resmi bir tanım verildiğinde, soru, bir StrongApplicativeörneğin varlığının sabit ve değişken büyüklükteki işlevleri kesin olarak ayırt edip etmediğidir .
Mevcut bir resmi tanımın farkında olmadan, "sabit boyut" terimini kullanmamda sezgiye itiraz ediyorum. Bununla birlikte, birisi zaten bir fontörün büyüklüğü için mevcut bir formalizmi biliyorsa ve StrongApplicativeonunla kıyaslayabilirse , çok daha iyi.
** "Çokluk" ifadesiyle, gevşek bir şekilde, functor'ın codomain türünün bir sakininde functor'ın parametre tipindeki keyfi öğelerin "kaç" olduğunu ifade ediyorum. Bu olmadan funktor uygulanır belirli bir tipine ilişkin olarak, ve bu nedenle parametre türü belirli herhangi bir sakinlerine bakılmaksızın.
Bu konuda kesin olmamak yorumlarda karışıklığa neden oldu, bu yüzden çeşitli functorların boyutunu / çokluğunu dikkate alacağımın bazı örnekleri:
VoidF: sabit, 0Identity: sabit, 1Maybe: değişken, minimum 0, maksimum 1[]: değişken, minimum 0, maksimum sonsuzNonEmptyList: değişken, minimum 1, maksimum sonsuzStream: sabit, sonsuzMonoid m => (,) m: sabit, 1data Pair a = Pair a a: sabit, 2Either x: değişken, minimum 0, maksimum 1data Strange a = L a | R a: sabit, 1
(->) rbunlar doğru şekilde izomorfiktir.
(->) r; güçlü uygulama yapısını korumak için izomorfizmin bileşenlerine ihtiyacınız vardır. Herhangi bir nedenle RepresentableHaskell'deki tip sınıfının gizemli bir tabulate . return = returnyasası var (monadik olmayan functors için gerçekten mantıklı bile değil), ancak bunu söylememiz gereken koşulların 1 / 4'ünü veriyor tabulateve zipuygun bir monoid kategorisinin morfizmleri. . Diğer üçü ise talep etmeniz gereken ekstra yasalardır.
tabulateve indexuygun bir kategorinin morfizmleri ..." olmalıdır
returnciddi bir sorun değildir. cotraverse getConst . Const, return/ pureaçısından varsayılan bir uygulamadır Distributiveve dağıtımcılar / temsil edilebilirler sabit bir şekle sahip olduğundan, bu uygulama benzersizdir.