Bu soruyu cevaplamak için daha sistematik bir yaklaşım önermek ve ayrıca "alt" değerler veya sonsuz veri türleri ya da bunun gibi herhangi bir özel numara kullanmayan örnekler göstermek istiyorum.
Yazım yapıcıları ne zaman yazım sınıfı örnekleri içeremez?
Genel olarak, bir tür yapıcısının belirli bir tür sınıfının bir örneğine sahip olamamasının iki nedeni vardır:
- Tür sınıfından gerekli yöntemlerin tür imzaları uygulanamıyor.
- Tip imzalarını uygulayabilir, ancak gerekli yasaları karşılayamaz.
Birinci türden örnekler ikinci türden daha kolaydır, çünkü ilk tür için, sadece belirli bir tip imzası olan bir işlevi yerine getirip getiremeyeceğini kontrol etmemiz gerekir, ikinci tür için ise hiçbir uygulamanın olmadığını kanıtlamamız gerekir. yasaları yerine getirebilirdi.
Özel örnekler
Bu, tür parametresine göre bir functor değil, bir kontrüktördür a
, çünkü a
kontravaryant bir konumdadır. Tip imzalı bir fonksiyon uygulamak imkansızdır (a -> b) -> F z a -> F z b
.
Türü imzası uygulanabilse fmap
de yasal bir işlev olmayan bir tür oluşturucu :
data Q a = Q(a -> Int, a)
fmap :: (a -> b) -> Q a -> Q b
fmap f (Q(g, x)) = Q(\_ -> g x, f x) -- this fails the functor laws!
Bu örneğin meraklı yönü o zamanın olabilir uygulamak fmap
rağmen doğru tipte F
kullandığı çünkü muhtemelen bir funktor olamaz a
bir kontravaryant konumda. Bu nedenle, fmap
yukarıda gösterilen bu uygulama yanıltıcıdır - doğru tip imzasına sahip olmasına rağmen (bunun bu tip imzanın tek olası uygulaması olduğuna inanıyorum), functor yasaları tatmin olmuyor. Örneğin, fmap id
≠ id
çünkü let (Q(f,_)) = fmap id (Q(read,"123")) in f "456"
olduğunu 123
, ancak let (Q(f,_)) = id (Q(read,"123")) in f "456"
bir 456
.
Aslında, F
sadece bir profiktör, - ne bir fonktor ne de bir konfunktor.
Tür imzası uygulanamayacağı pure
için geçerli olmayan yasal bir işlev : Yazar monadını alın (a, w)
ve w
bir monoid olması gereken kısıtlamayı kaldırın . Tür bir değer oluşturmak için daha sonra imkansız (a, w)
üzerinden a
.
Türünün imzası <*>
uygulanamadığı için uygulanabilir olmayan bir işlevdata F a = Either (Int -> a) (String -> a)
.
Tür sınıfı yöntemleri uygulanabilse bile yasal olarak geçerli olmayan bir işlevci :
data P a = P ((a -> Int) -> Maybe a)
Tür yapıcısı P
, a
yalnızca kovaryant konumlarda kullandığı için bir işlevcidir .
instance Functor P where
fmap :: (a -> b) -> P a -> P b
fmap fab (P pa) = P (\q -> fmap fab $ pa (q . fab))
Türünün imzasının tek olası uygulaması <*>
her zaman dönen bir işlevdir Nothing
:
(<*>) :: P (a -> b) -> P a -> P b
(P pfab) <*> (P pa) = \_ -> Nothing -- fails the laws!
Ancak bu uygulama, uygulamalı işlevler için kimlik yasasını karşılamamaktadır.
Applicative
Monad
Türü imzası bind
uygulanamadığı için olan ancak olmayan bir işlev .
Böyle bir örnek bilmiyorum!
- A funktor
Applicative
ancak birMonad
yasa türü imzası olsa memnun olamaz çünkü bind
uygulanabilir.
Bu örnek biraz tartışma yarattı, bu nedenle bu örneğin doğru olduğunu kanıtlamanın kolay olmadığını söylemek güvenlidir. Ancak birkaç kişi bunu farklı yöntemlerle bağımsız olarak doğruladı. Bkz. `Veri PoE a = Boş | Çifte bir monad mı? ek tartışma için.
data B a = Maybe (a, a)
deriving Functor
instance Applicative B where
pure x = Just (x, x)
b1 <*> b2 = case (b1, b2) of
(Just (x1, y1), Just (x2, y2)) -> Just((x1, x2), (y1, y2))
_ -> Nothing
Yasal bir Monad
örnek olmadığını kanıtlamak biraz zahmetlidir . Monadik olmayan davranışın nedeni bind
, bir fonksiyonun ne zaman f :: a -> B b
geri dönebileceği Nothing
veya Just
farklı değerleri için uygulanmanın doğal bir yolu olmamasıdır a
.
Belki Maybe (a, a, a)
de bir monad olmayan düşünmek ve bunun için uygulamayı denemek daha açıktır join
. Birisi sezgisel olarak makul bir uygulama yolu bulunmayacaktır join
.
join :: Maybe (Maybe (a, a, a), Maybe (a, a, a), Maybe (a, a, a)) -> Maybe (a, a, a)
join Nothing = Nothing
join Just (Nothing, Just (x1,x2,x3), Just (y1,y2,y3)) = ???
join Just (Just (x1,x2,x3), Nothing, Just (y1,y2,y3)) = ???
-- etc.
İle belirtilen durumlarda , altı farklı tip değerden makul ve simetrik bir şekilde ???
üretemeyeceğimiz açıktır . Kesinlikle bu altı değerin keyfi bir alt kümesini seçebiliriz - örneğin, her zaman ilk işsizliği alırız - ancak bu, monadın yasalarını karşılamaz. Geri dönmek de yasaları yerine getirmeyecektir.Just (z1, z2, z3)
a
Maybe
Nothing
- Ağaç benzeri bir veri yapısı , çağrışım yapmasına rağmen bir monad olmayan
bind
- ancak kimlik yasalarında başarısız olur.
Her zamanki ağaç benzeri monad (veya "functor şekilli dalları olan bir ağaç")
data Tr f a = Leaf a | Branch (f (Tr f a))
Bu, functor üzerinde serbest bir monad f
. Verilerin şekli, her dallanma noktasının alt ağaçların "işlev-ful" olduğu bir ağaçtır. Standart ikili ağaç ile elde edilir type f a = (a, a)
.
Bu veri yapısını yaprakları da functor şeklinde yaparak değiştirirsek f
, "semimonad" dediğim şeyi elde ederiz - bind
doğallığı ve ilişkilendirilebilirlik yasalarını tatmin eden, ancak pure
yöntemi kimlik yasalarından birinde başarısız olur. "Semimonads endofunktor kategorisindeki yarıgruplar, sorun nedir?" Bu tip sınıfıdır Bind
.
Basitlik için, join
yerine yöntem tanımlamak bind
:
data Trs f a = Leaf (f a) | Branch (f (Trs f a))
join :: Trs f (Trs f a) -> Trs f a
join (Leaf ftrs) = Branch ftrs
join (Branch ftrstrs) = Branch (fmap @f join ftrstrs)
Dal aşılama standarttır, ancak yaprak aşılama standart değildir ve a üretir Branch
. Bu, ilişkilendirilebilirlik yasası için bir sorun değildir, ancak kimlik yasalarından birini ihlal eder.
Polinom tiplerinde ne zaman monad örnekleri bulunur?
Her ikisi de functor Maybe (a, a)
ve açıkça olsa da Maybe (a, a, a)
yasal bir Monad
örnek verilemez Applicative
.
Bu işlevlerin hiçbir hilesi yoktur - hayır Void
veya bottom
hiçbir yerde, zor tembellik / katılık, sonsuz yapılar ve tip sınıf kısıtlamaları yoktur. Applicative
Örneğin tamamen standarttır. Fonksiyonları return
ve bind
bu functors için uygulanabilir, ancak monad yasalarını yerine getirmez. Başka bir deyişle, belirli bir yapı eksik olduğu için bu işlevler monad değildir (ancak tam olarak neyin eksik olduğunu anlamak kolay değildir). Örnek olarak, işlevdeki küçük bir değişiklik onu bir monad haline getirebilir: data Maybe a = Nothing | Just a
bir monaddır. Başka bir benzer işlev data P12 a = Either a (a, a)
de bir monaddır.
Polinom monadlar için inşaatlar
Genel olarak, burada Monad
polinom türlerinden yasal olanları üreten bazı yapılar var . Tüm bu yapılarda M
bir monad var:
type M a = Either c (w, a)
w
herhangi bir monoid nerede
type M a = m (Either c (w, a))
m
herhangi bir monad nerede ve w
herhangi bir monoid
type M a = (m1 a, m2 a)
nerede m1
ve m2
herhangi bir monad
type M a = Either a (m a)
m
herhangi bir monad nerede
İlk inşaat, WriterT w (Either c)
ikinci inşaat WriterT w (EitherT c m)
. Üçüncü yapı monads bir bileşeni-bazlı üründür pure @M
bileşen-bazlı ürün olarak tanımlanır pure @m1
ve pure @m2
ve join @M
(örneğin, çapraz-ürün verilerini atlanması ile tanımlanır m1 (m1 a, m2 a)
eşleştirilir m1 (m1 a)
başlığın ikinci kısmını iptal edilerek):
join :: (m1 (m1 a, m2 a), m2 (m1 a, m2 a)) -> (m1 a, m2 a)
join (m1x, m2x) = (join @m1 (fmap fst m1x), join @m2 (fmap snd m2x))
Dördüncü yapı şu şekilde tanımlanır:
data M m a = Either a (m a)
instance Monad m => Monad M m where
pure x = Left x
join :: Either (M m a) (m (M m a)) -> M m a
join (Left mma) = mma
join (Right me) = Right $ join @m $ fmap @m squash me where
squash :: M m a -> m a
squash (Left x) = pure @m x
squash (Right ma) = ma
Dört yapının da yasal monad ürettiğini kontrol ettim.
Ben varsayım polinom monads için başka yapılar olduğunu. Örneğin, Maybe (Either (a, a) (a, a, a, a))
bu yapıların hiçbiri yoluyla işlev elde edilmez ve dolayısıyla monadik değildir. Ancak, Either (a, a) (a, a, a)
bu üç monad'ların ürüne izomorftur çünkü monadic olduğunu a
, a
ve Maybe a
. Ayrıca, Either (a,a) (a,a,a,a)
bu ürünü izomorftur çünkü monadic olduğunu a
ve Either a (a, a, a)
.
Yukarıda gösterilen dört yapı a
, örneğin herhangi bir sayıdaki herhangi bir sayıda ürünün herhangi bir toplamını elde etmemizi sağlayacaktır Either (Either (a, a) (a, a, a, a)) (a, a, a, a, a))
. Bu tür tüm yapıcıların (en az bir) Monad
örneği olacaktır.
Tabii ki, bu tür monadlar için hangi kullanım durumlarının mevcut olabileceği görülüyor. Başka bir konu, Monad
1-4 . Yapılarla türetilmiş örneklerin genel olarak benzersiz olmamasıdır. Örneğin, tip yapıcısına iki şekilde type F a = Either a (a, a)
bir Monad
örnek verilebilir : monad kullanılarak yapı 4 ile (a, a)
ve izomorfizm türü kullanılarak yapı 3 ile Either a (a, a) = (a, Maybe a)
. Yine, bu uygulamalar için kullanım örnekleri bulmak hemen belli değildir.
Bir soru var - keyfi bir polinom veri türü verildiğinde, bir Monad
örneğinin olup olmadığını nasıl anlayacağım . Polinom monadlar için başka yapı olmadığını nasıl kanıtlayacağımı bilmiyorum. Bu soruyu cevaplamak için şu ana kadar herhangi bir teori olduğunu düşünmüyorum.
* -> *
) yapmak mümkün müdür ?fmap