13

kullanıcı 'singpolyma' asked on reddit orada yatan bazı genel yapısı ise: Ücretsiz bir monad önerildiUygulama sirkülasyonlarının bileşimi aracılığıyla kısa devre arızasıyla başarıların listesini oluşturabilir miyim?

data FailList a e = Done | Next a (FailList a e) | Fail e 

, ancak bu uygulamalı functors aracılığıyla daha genel model alınarak belirlenebileceğini merak ettim. Bazerman, Abstracting with Applicatives numaralı telefondan bize, iki uygulamalı funktörün toplamının, önyargı doğrultusunda doğal bir dönüşüme sahip olmamız koşuluyla, sol/sağa eğilimli, uygulamalı bir functor olduğunu göstermektedir. Bu ihtiyacımız olan şey gibi geliyor! Böylece teklifime başladım, ancak daha sonra hızla problemlerle karşılaştım. Herkes bu sorunlara çözümler görüyor mu ?:


İlk olarak, iki çekicinin toplamının tanımıyla başlıyoruz. Buraya başladım çünkü toplam türlerini modellemek istiyoruz - başarılar ya da başarılar ve başarısızlık.

data Sum f g a = InL (f a) | InR (g a) 

Ve çalışmak istediğiniz iki fanktorlar şunlardır:

data Success a = Success [a] 
data Failure e a = Failure e [a] 

Success basittir - aslında Const [a] bu. Ancak, Failure e Bundan emin değilim. pure herhangi bir tanıma sahip olmadığı için, uygulama amaçlı bir eğlence aracı değildir.

instance Functor Success where 
    fmap f (Success a) = Success a 

instance Functor (Failure e) where 
    fmap f (Failure e a) = Failure e a 

instance Apply (Failure e) where 
    (Failure e a) <.> (Failure _ b) = Failure e a 

instance Apply Success where 
    (Success a) <.> (Success b) = Success (a <> b) 

instance Applicative Success where 
    pure = const (Success []) 
    a <*> b = a <.> b 

Daha sonra, sağdan sola doğru doğal bir dönüşüm ile, bu functors toplamını tanımlayabilir (yani sol ön gerilim):

instance (Apply f, Apply g, Applicative g, Natural g f) => Applicative (Sum f g) where 
    pure x = InR $ pure x 
    (InL f) <*> (InL x) = InL (f <*> x) 
    (InR g) <*> (InR y) = InR (g <*> y) 
    (InL f) <*> (InR x) = InL (f <.> eta x) 
    (InR g) <*> (InL x) = InL (eta g <.> x) 

Ancak, Apply bir örneğidir Ve şimdi yapmamız gereken tek şey, doğal dönüşümümüzü tanımlamaktır ve burası her şeyin çöküşüdür.

instance Natural Success (Failure e) where 
    eta (Success a) = Failure ???? a 

oluşturmak için yetersizlik bir Failure sorun gibi görünüyor. Ayrıca, hacky olmak ve ⊥ kullanmak bir seçenek değildir, çünkü bu , InR (Success ...) <*> InL (Failure ...) bulunduğunuz durumda değerlendirilecektir.

Bir şeyleri kaçırıyormuş gibi hissediyorum, ama ne olduğu hakkında hiçbir fikrim yok.

Bu yapılabilir mi?

+0

Doğallık koşulu forall (f :: a -> b). eta. fmap f == fmap f. eta, hata bileşeninin sabit olması gerektiğini kuvvetle önerir. Bu bana bir 'Varsayılan e => Uygulayıcı (Başarısız e)' yazmamı sağlıyor. –

+1

Ayrıca, Uygulamanızın/Uygulamanızın örnekleri tuhaf. Kafaları sıkıca kontrol ettim, ama genelde tip kontrol etmiyorlar! 'Başarı a' aslında 'Sabit [a]' ya değil, en azından, daha fazla tip indekslere ihtiyaç duyar. –

+0

@tel - 'Varsayılan 'mümkün görünüyor, sadece bir aklı başında" varsayılan hata mesajı "olacağını göremiyorum. Ayrıca, düzenlemeleriniz geçerli olmakla birlikte diğer SO editörleri tarafından reddedildi. Onları kendim uygularım. – ocharles

cevap

4

"Doğru" cevabın, reddit tartışması hakkındaki fikri beğenmediğiniz kadarıyla e'u bir kandırmak olduğunun gayet eminim.

Failure "oops" [(*1),(*2),(*3)] <*> Failure "doh" [1,2,3]'u düşünün Sonuçta "oops" veya "doh" hatası var mı?e bir monoid yaparak hiçbir kanonik seçim olduğu gerçeğini yakalamak ve tüketici kendi zehri seçelim (ister First, Last, [] vs.)

Not bu çözümün olduğunakanaat (Maybe e, [a]) temsil gibi, Akım/potansiyel olarak sonsuz verilerle doğru bir şekilde ilgilenmez, çünkü listeyi sonlandıran bir hatamız olup olmadığı konusunda katıdır.

Farklı bir kodlama, izleme noktası (http://comonad.com/reader/2013/algebras-of-applicatives/) uyarınca, uygulamaların düzeltme noktalarını kullanır. Sonra

liste gösterimi orada (FixF (ProductF Embed (Sum (Const()))) a) sunulan almak ve birim pozisyonda hata Monoid yapışmasını bir değerle değiştirin, şu olsun:

Monid mon => FixF (ProductF Embed (Sum (Const mon))) a

Ve kullanma unutmayın bir FailList tam olarak FailList olsun, ancak FailList ile olduğu gibi bir hata yerine, birleştirme hataları doğru bir yolu belirterek yazmadan bir uygulama örneği almak için.

Ayrıca sonra geri almak fixpoint yaklaşımla biz Success [(*1),(*2),(*3)] <*> Failure "doh" [1,2,3,4,5] eşdeğer varsa unutmayın üç elemanlı bir Success (yani biz başarısızlıkla gerçekten nonstrict vardır) önerdiğiniz yaklaşımda, geri bir Failure üç ile alırken elemanlar ve beş eleman başarısız listesi listesindeki hata. Bu, akışa karşı katı değişimlerdir.

Son olarak, en basit şekilde, standart uygulama makinelerini kullanmak ve orijinal veri tipine çok yakın bir şey almak için type FailList e = Product (Const (First e)) ZipList numaralı telefonu alabiliriz.

2
{-# LANGUAGE FlexibleInstances #-} 

instance Applicative (Sum Success (Failure e)) where 
    pure x = InL $ pure x 
    (InL f) <*> (InL x) = InL (f <*> x) 
    (InR (Failure e fs)) <*> (InR (Failure _ gs)) = InR (Failure e (fs <*> gs)) 
    (InR (Failure e fs)) <*> (InL (Success gs)) = InR (Failure e (fs <*> gs)) 
    (InL (Success gs)) <*> (InR (Failure e fs)) = InR (Failure e (gs <*> fs)) 

hep başarılarla listesine bir başarısızlık ekleyebilir Bunun nedeni; Ayrıca bu tip sınıfı yerine Natural f g kullanabilir

):

class Transplant f g where 
    transplant :: f a -> g b -> f b 

instance Transplant (Failure e) Success where 
    transplant (Failure e _) (Success a) = Failure e a 

Fikrim Yok neyi bunu kategori-teori-bilge anlamına gelir.

+0

Yea, "Başarı"/"Başarısızlık" için özel bir "Uygulayıcı" örneği yazabileceğimin farkındayım, ancak bu, korumak istediğim "Sum" için genel örnekle çakışıyordu. Ayrıca, 'Başarısızlık'/'Başarı' kombinasyonuna ilişkin tanımlarınız tam olarak istediğim şey değildir, çünkü 'Başarısızlık' daha fazla başarıyı engellemelidir (sol/sağ taraf tamamen atılmalıdır). Transplate doğru çizgiler boyunca ilerliyor, ama ben onun altında yatan bazı fantezi kategori teorisi/soyut cebir yapı olup olmadığını merak ediyorum :) – ocharles

+0

Transplant kesinlikle el yazısı örneği ile aynı şekilde çalışır. 'Başarısızlık'/'Başarı' kombinasyonunu nasıl farklı bir şekilde tanımlayacağınızdan tam olarak emin değilim, bu mümkün mü? –

+0

Elbette, 'Transplant' iyi, ama tüm 'Sum' türleri için tanımlanmış olması gerekiyordu, bu yüzden sadece orada gerçek bir isim/kategori teorik kavramı veya başka herhangi bir yaklaşım olup olmadığını merak ediyorum. – ocharles