Functor / Functor / Uygulayıcı / Monad değil mi?


210

Birisine X tipi bir sınıfın ne olduğunu açıklarken, tam olarak X olan veri yapılarına iyi örnekler bulmak için mücadele ediyorum.

Bu yüzden aşağıdakiler için örnekler talep ediyorum:

  • Functor olmayan bir tür oluşturucu.
  • Functor olan ancak Uygulayıcı olmayan bir tür oluşturucu.
  • Uygulayıcı olan, ancak Monad olmayan bir tür kurucu.
  • Monad olan bir tür kurucu.

Her yerde çok sayıda Monad örneği olduğunu düşünüyorum, ancak önceki örneklerle bazı ilişkilere sahip iyi bir Monad örneği resmi tamamlayabilir.

Birbirine benzeyecek, sadece belirli sınıf sınıfına ait olmak için önemli yönlerinden farklı örnekler arıyorum.

Eğer kişi bu hiyerarşide bir yerde bir Ok örneğini gizleyebilseydi (Uygulayıcı ve Monad arasında mı?), Bu da harika olurdu!


4
Uygun olmayan bir tip yapıcı ( * -> *) yapmak mümkün müdür ? fmap
Owen

1
Owen, sanırım a -> Stringbir fontör değil.
Rotsor

3
@Rotsor @Owen a -> String, matematiksel bir işlevdir , ancak Functoraçık olması için bir Haskell değil .
J. Abrahamson

@J. Abrahamson, ne anlamda matematiksel bir işlev? Ters oklarla kategoriden mi bahsediyorsunuz?
Rotsor

3
İnsanlar bilmiyorum, bir kontravaryant funktor türünde bir fmap sahiptir(a -> b) -> f b -> f a
AJFarmar

Yanıtlar:


100

Functor olmayan bir tür oluşturucu:

newtype T a = T (a -> Int)

Bunun dışında bir kontravaryant fonksiyon oluşturursunuz, ancak (kovaryant) fonksiyon oluşturmaz. Yazmayı deneyin, fmapbaşarısız olacaksınız. Kontravaryant fonksiyoner versiyonunun tersine çevrildiğine dikkat edin:

fmap      :: Functor f       => (a -> b) -> f a -> f b
contramap :: Contravariant f => (a -> b) -> f b -> f a

Functor olan ancak Uygulayıcı olmayan bir tür oluşturucu:

İyi bir örneğim yok. Var Const, ama ideal olarak somut bir Monoid olmayan istiyorum ve hiçbirini düşünemiyorum. Tüm türler temelde sayısal, sayılar, ürünler, toplamlar veya aşağı indiğinizde işlevlerdir. Aşağıda pigworker görebilirsiniz ve ben Data.Voidbir olup olmadığını katılmıyorum Monoid;

instance Monoid Data.Void where
    mempty = undefined
    mappend _ _ = undefined
    mconcat _ = undefined

Yana _|_Haskell yasal değerdir ve aslında sadece yasal değeri Data.Void, bu Monoid kurallarını karşılar. Bununla ne unsafeCoerceyapacağından emin değilim , çünkü programınızın herhangi bir unsafeişlevi kullandığınız anda Haskell semantiğini ihlal etmemesi garanti edilmiyor .

Altta ( bağlantı ) veya güvenli olmayan işlevlerde ( bağlantı ) bir makale için Haskell Wiki'ye bakın .

Acaba Agda veya Haskell gibi daha zengin bir sistem kullanarak çeşitli uzantılara sahip böyle bir yapıcı oluşturmanın mümkün olup olmadığını merak ediyorum.

Uygulayıcı olan, ancak bir Monad olmayan bir tür kurucu:

newtype T a = T {multidimensional array of a}

Bunun gibi bir şeyle bir Başvuru yapabilirsiniz:

mkarray [(+10), (+100), id] <*> mkarray [1, 2]
  == mkarray [[11, 101, 1], [12, 102, 2]]

Ama bunu bir monad yaparsanız, bir boyut uyuşmazlığı elde edebilirsiniz. Bunun gibi örneklerin pratikte nadir olduğunu düşünüyorum.

Monad olan bir tür kurucu:

[]

Oklar Hakkında:

Bir Ok'un bu hiyerarşide nerede yattığını sormak, "kırmızı" nın ne tür bir şekil olduğunu sormak gibidir. Tür uyumsuzluğuna dikkat edin:

Functor :: * -> *
Applicative :: * -> *
Monad :: * -> *

fakat,

Arrow :: * -> * -> *

3
İyi liste! Either aAnlamak daha kolay olduğu için, son durum için örnek olarak daha basit bir şey kullanmanızı öneririm .
fuz

6
Hâlâ Uygulamalı olan ancak bir Monad olmayan bir tür oluşturucu arıyorsanız, çok yaygın bir örnek olacaktır ZipList.
John L

23
_|_* içinde her tipte yaşar, ama asıl mesele, Voidbir tane inşa etmek için geriye doğru eğilmeniz veya değerini yok etmenizdir. Vb Enum, Monoid, onun değil bir örneği Eğer zaten mevcut ise neden ben onları birlikte püre bildirmekten mutluluk duyuyorum olduğunu (size vererek Semigroup) ancak mempty, ama açıkça türünde bir değer oluşturmak için bir araç vermek Voidiçinde void. Silahı yüklemeli ve ayağınıza doğrultmalı ve tetiği kendiniz çekmelisiniz.
Edward KMETT

2
Bilgiçlikle, sanırım Cofunctor fikriniz yanlış. Bir işlevin ikilisi bir işleçtir, çünkü hem girdiyi hem de çıktıyı çevirirsiniz ve aynı şeyle sonuçlanırsınız. Aradığınız fikir, muhtemelen biraz farklı olan “karşıt değişken functor” dur.
Ben Millwood

1
@AlexVong: "Kullanımdan kaldırıldı" -> insanlar sadece farklı bir paket kullanıyor. Karşıtlık için özür dilerim, "functor ikili" değil "kontravaryant functor" hakkında konuşmak. Bazı bağlamlarda, "eşdeğişken" işlevini "kontravaryant işlevler" olarak adlandırdığımı gördüm, çünkü işlevler kendi kendini ikiye katlıyor, ama bu sadece insanları kafa karıştırıyor gibi görünüyor.
Dietrich Epp

87

Tarzım telefonum tarafından sıkışık olabilir, ama işte gidiyor.

newtype Not x = Kill {kill :: x -> Void}

Functor olamaz. Olsaydı, biz olurdu

kill (fmap (const ()) (Kill id)) () :: Void

ve Ay yeşil peynirden yapılmış olacaktı.

o esnada

newtype Dead x = Oops {oops :: Void}

bir fontör

instance Functor Dead where
  fmap f (Oops corpse) = Oops corpse

ama uygulanabilir olamaz, ya da

oops (pure ()) :: Void

ve Yeşil Ay peynirinden (aslında olabilir, ancak daha sonra akşamları) yapılır.

(Ekstra not: Void, olduğu gibi Data.Voidboş bir veri türüdür kullanmak deneyin. undefinedBir Monoid olduğunu kanıtlamak için, ben kullanacağız unsafeCoercebunun olmadığını kanıtlamak için.)

Sevinçle,

newtype Boo x = Boo {boo :: Bool}

Dijkstra'nın sahip olduğu gibi birçok açıdan uygulanabilir,

instance Applicative Boo where
  pure _ = Boo True
  Boo b1 <*> Boo b2 = Boo (b1 == b2)

ama bir Monad olamaz. Neden olmadığını görmek için, geri dönüşün sürekli olması gerektiğini Boo Trueveya Boo Falsedolayısıyla

join . return == id

muhtemelen dayanamaz.

Oh evet, neredeyse unutuyordum

newtype Thud x = The {only :: ()}

bir Monad. Kendininkini yuvarla.

Uçak yakalamak için ...


8
Boşluk boş! Her neyse ahlaki olarak.
pigworker

9
Void, 0 yapıcılı bir tür olduğunu düşünüyorum. Bu bir monoid değildir çünkü yoktur mempty.
Rotsor

6
Tanımsız? Ne kaba! Ne yazık ki, unsafeCoerce (unsafeCoerce () <*> undefined) değil (), bu yüzden gerçek hayatta yasaları ihlal eden gözlemler var.
pigworker

5
Tanımlanamayan bir tür tahammül eden olağan anlambilimde, haklısınız. Elbette başka anlambilimler de var. Boşluk, toplam fragmandaki bir submonoid ile sınırlı değildir. Bir anlambilimde başarısızlık biçimlerini ayıran bir monoid de değildir. Telefon tabanlı düzenlemeden daha kolay bir anım olduğunda, örneğimin yalnızca tam olarak bir tür tanımlanmamış bir anlambilimde çalıştığını açıklığa kavuşturacağım.
pigworker

22
Hakkında çok ado_|_
Landei

71

Diğer cevapların bazı basit ve yaygın örnekleri kaçırdığına inanıyorum:

Functor olan ancak Uygulayıcı olmayan bir tür kurucu. Basit bir örnek bir çifttir:

instance Functor ((,) r) where
    fmap f (x,y) = (x, f y)

Ancak, Applicativeek kısıtlamalar getirmeden örneğini nasıl tanımlayacağının bir yolu yoktur r. Özellikle, pure :: a -> (r, a)keyfi bir şekilde tanımlamanın bir yolu yoktur r.

Uygulayıcı olan, ancak Monad olmayan bir tür kurucu. İyi bilinen bir örnek ZipList'tir . ( newtypeListeleri saran ve Applicativeonlar için farklı örnekler sunan bir dosyadır.)

fmap"" her zamanki gibi tanımlanır. Ama pureve <*>olarak tanımlanır

pure x                    = ZipList (repeat x)
ZipList fs <*> ZipList xs = ZipList (zipWith id fs xs)

böylece pureverilen değeri tekrarlayarak sonsuz bir liste oluşturur ve <*>bir işlevler listesini değerler listesiyle sıkıştırır - i- işlevini i- öğeye uygular . (Standart <*>, j- elementine i - th fonksiyonunun []uygulanmasının tüm olası kombinasyonlarını üretir .) Ancak bir monadın nasıl tanımlanacağı mantıklı bir yolu yoktur ( bu gönderiye bakınız ).


Oklar işleve / uygulanabilir / monad hiyerarşisine nasıl sığar? Bkz Deyimler monads gelecek vaad etmektedir, oklar titiz, habersiz olan Sam Lindley Philip bakınız, Wadler Jeremy Yallop tarafından. MSFP 2008. (Uygulayıcı işlev deyimlerini çağırırlar .) Özet:

Üç hesaplama kavramı arasındaki bağlantıya tekrar bakıyoruz: Moggi'nin monadları, Hughes'un okları ve McBride ve Paterson'un deyimleri (aynı zamanda uygulamalı functors olarak da bilinir). Deyimlerin A ~> B = 1 ~> (A -> B) tip izomorfizmini karşılayan oklara eşdeğer olduğunu ve monadların A ~> B = A -> (1 ~ tip izomorfizmini karşılayan oklara eşdeğer olduğunu gösteriyoruz. > B). Ayrıca, deyimler oklara, oklar da monadlara gömülür.


1
Yani ((,) r)bir uygulamalı olmayan bir funktoru olduğu; ancak bunun nedeni genellikle bir kerede pureherkes için tanımlayamamanızdır r. Bu bir tanımla uygulamalı functors bir (sonsuz) koleksiyonunu tanımlamak için çalışmak yerine, bu nedenle dil özlü bir cilvesi var pureve <*>; Bu anlamda, herhangi bir beton için, çünkü bu karşı örnek hakkında matematiksel derin bir şey olmak görünmüyor r, ((,) r) olabilir bir uygulamalı functor yapılabilir. Soru: Başvuru sahibi olamayan bir BETON işlevini düşünebilir misiniz?
George

1
Bu soruya yazı olarak stackoverflow.com/questions/44125484/… adresine bakın .
George

20

İşlev olmayan bir tür oluşturucu için iyi bir örnek Set: Uygulayamazsınız fmap :: (a -> b) -> f a -> f b, çünkü ek bir kısıtlama olmadan Ord binşa edemezsiniz f b.


16
Matematiksel olarak bunu gerçekten bir işlev haline getirmek istediğimiz için aslında iyi bir örnek .
Alexandre C.

21
@AlexandreC. Buna katılmıyorum, iyi bir örnek değil. Matematiksel olarak, böyle bir veri yapısı bir işlev oluşturur. Uygulayamadığımız gerçeği fmapsadece bir dil / uygulama meselesidir. Ayrıca, Setbeklediğimiz tüm özelliklerle bir monad yapan bir devam monadına sarmak mümkündür , bu soruyu görün (ancak verimli bir şekilde yapılıp yapılamayacağından emin değilim).
Petr Pudlák

@PetrPudlak, bu nasıl bir dil sorunu? Eşitliği bkararsız olabilir, bu durumda tanımlayamazsınız fmap!
Turion

@Turion Karar verilebilir ve tanımlanabilir olmak iki farklı şeydir. Örneğin, bir algoritma ile karar vermek mümkün olmasa da, lambda terimleri (programları) üzerinde eşitliği doğru bir şekilde tanımlamak mümkündür. Her durumda, bu örnekte durum böyle değildi. Burada sorun, bir Functorörneği Ordkısıtlama ile tanımlayamamamızdır , ancak farklı bir tanım Functorveya daha iyi dil desteği ile mümkün olabilir . Aslında ConstraintKinds ile bu şekilde parametreleştirilebilen bir tip sınıfı tanımlamak mümkündür .
Petr Pudlák

ordKısıtlamanın üstesinden gelebilsek bile, a'nın Setyinelenen girişler içerememesi fmap, bağlamı değiştirebilecek anlamına gelir . Bu birliktelik yasasını ihlal eder.
John F. Miller

11

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:

  1. Tür sınıfından gerekli yöntemlerin tür imzaları uygulanamıyor.
  2. 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

  • Tür uygulanamadığı için işlev örneği bulunamayan bir tür yapıcısı :

    data F z a = F (a -> z)

Bu, tür parametresine göre bir functor değil, bir kontrüktördür a, çünkü akontravaryant bir konumdadır. Tip imzalı bir fonksiyon uygulamak imkansızdır (a -> b) -> F z a -> F z b.

  • Türü imzası uygulanabilse fmapde 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 fmaprağmen doğru tipte Fkullandığı çünkü muhtemelen bir funktor olamaz abir kontravaryant konumda. Bu nedenle, fmapyukarı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 ididçü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, Fsadece bir profiktör, - ne bir fonktor ne de bir konfunktor.

  • Tür imzası uygulanamayacağı pureiçin geçerli olmayan yasal bir işlev : Yazar monadını alın (a, w)ve wbir 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, ayalnı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.

  • ApplicativeMonadTürü imzası binduygulanamadığı için olan ancak olmayan bir işlev .

Böyle bir örnek bilmiyorum!

  • A funktor Applicativeancak birMonad yasa türü imzası olsa memnun olamaz çünkü binduygulanabilir.

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 bgeri dönebileceği Nothingveya Justfarklı 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)aMaybeNothing

  • Ağaç benzeri bir veri yapısı , çağrışım yapmasına rağmen bir monad olmayanbind - 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 - binddoğallığı ve ilişkilendirilebilirlik yasalarını tatmin eden, ancak pureyö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, joinyerine 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 Voidveya bottomhiç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ı returnve bindbu 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 abir 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 Monadpolinom türlerinden yasal olanları üreten bazı yapılar var . Tüm bu yapılarda Mbir monad var:

  1. type M a = Either c (w, a)wherhangi bir monoid nerede
  2. type M a = m (Either c (w, a))mherhangi bir monad nerede ve wherhangi bir monoid
  3. type M a = (m1 a, m2 a)nerede m1ve m2herhangi bir monad
  4. type M a = Either a (m a)mherhangi 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 @Mbileşen-bazlı ürün olarak tanımlanır pure @m1ve pure @m2ve 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, ave Maybe a. Ayrıca, Either (a,a) (a,a,a,a)bu ürünü izomorftur çünkü monadic olduğunu ave 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, Monad1-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.


Bence B olduğunu bir monad. Bu bağlama bir karşı örnek verebilir misiniz Pair x y >>= f = case (f x, f y) of (Pair x' _,Pair _ y') -> Pair x' y' ; _ -> Empty?
Franky

@Franky Birleşim seçtiğiniz bu tanım ile başarısız fböyle f xolduğunu Emptyama f ybir olduğunu Pairve bir sonraki adımda hem Pair. El ile yasaların bu uygulama veya başka bir uygulama için geçerli olmadığını kontrol ettim. Ama bunu yapmak oldukça adil bir iş. Keşke bunu anlamanın daha kolay bir yolu olsaydı!
winitzki

1
@Turion Bu argüman için geçerli değildir Maybeçünkü endişelenecek Maybefarklı değerler içermez a.
Daniel Wagner

1
@Turion Bunu birkaç sayfa hesaplama ile kanıtladım; "doğal yol" tartışması sadece sezgisel bir açıklamadır. Bir Monadörnek işlevleri oluşur returnve bindtatmin yasalara söyledi. Gerekli tiplere uyan iki uygulama returnve 25 uygulama bindvardır. Doğrudan hesaplamayla, uygulamaların hiçbirinin yasaları karşılamadığını gösterebilirsiniz. Gerekli iş miktarını azaltmak için önce kimlik yasalarını joinyerine bindkullandım ve kullandım. Ama bu oldukça fazla işti.
winitzki

1
@duplode Hayır, Traversablegerekli olduğunu sanmıyorum . m (Either a (m a))kullanılarak pure @mdönüştürülür m (Either (m a) (m a)). Sonra önemsiz Either (m a) (m a) -> m ave kullanabilirsiniz join @m. Kanunları kontrol ettiğim uygulama buydu.
winitzki
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.