2012-06-22 31 views
18

GHC, Haskell 98'de izin verilenler dışındaki tür sınıfları için türetilmiş örneklerin derleyici oluşturulmasına olanak tanıyan DeriveFunctor, DeriveDataTypeable vb. Gibi birkaç dil işaretine sahiptir. Bu, özellikle bu sınıfın yasalarının olduğu Functor gibi bir şey için mantıklıdır. Açık bir "doğal" türetilmiş örnek dikte.Neden GHC Monoid için örnek oluşturamıyor?

Neden Monoid için değil? (Pseudocode mazur)

data T = MkT a b c ... 

biri mekanik olarak bir Monoid örneğini üretmek olabilir: Tek veri yapıcısı ile herhangi bir veri türü için gibi görünüyor

instance (Monoid a, Monoid b, Monoid c, ...) => Monoid T where 
    mempty = 
    MkT mempty mempty mempty ... 
    mappend (MkT a1 b1 c1 ...) (MkT a2 b2 c2 ...) = 
    MkT (mappend a1 a2) (mappend b1 b2) (mappend c1 c2) ... 

şeyin farkındayım derive paket provides this, ama sorum, özellikle de GHC'nin yapmamasının bir nedeni olup olmadığıdır.

+0

@sdcvvc: Bu sorunun geçerli bir cevabı gibi görünüyor. Belki de böyle yazmalısın? –

+0

Tamam, bir cevap verdim. – sdcvvc

+1

Genellikle bir 'Functor' örneği oluşturmak için mantıklı bir yol var. Aynısı 'Monoid' hakkında da doğru değil. – augustss

cevap

14

Bu gerçekten Monoid türetmek mümkün olmayan bir karar, ancak monoidler de çok genel olduğundan, bir tür bir monoid yapmak için birçok yol vardır. İşte bir örnek:

data T = A | B | C deriving (Eq, Ord, Enum) 

type Mon a = (a, a -> a -> a) 

m1, m2, m3, m4 :: Mon T 
m1 = (A, max) 
m2 = (C, min) 
m3 = (A, \ x y -> toEnum $ (fromEnum x + fromEnum y) `rem` 3) 
m4 = (B, f4) 
f4 A _ = A 
f4 B x = x 
f4 C _ = C 

Bu (birimini ve ikili işlem içeren Mon ile) T bir monoid yapmak için dört makul yollarını gösterir. Bunlardan birincisi, azami almanın bir kısmıdır, ikincisi minimumdan almayı, üçüncüsü modülo aritmetikten üçüncüsü ve dördüncüsü ise Ordering tipi için kullanılan monoiddir. Hiçbir şey gerçekten doğal yol olarak göze çarpmıyor.

7

Aynı şeyi Num ve diğer bazı sınıflar için de sorabilirsiniz. Bu, önemsiz olacaktır: Diğer tüm standart türevler, çoklu kurucuları olan veri türleri için çalışır.

Yeni bir tür olarak, newtype T = MkT (a,b,c) deriving Monoid türetilen yeni tür kullanabilirsiniz.

Benzer uzantı: boş veri türünü neredeyse her tür sınıfın örneğini oluşturabilirsiniz.

deriving tümcesi, önceden tanımlanmış sınıflar için çalıştığı için Haskell'in her zaman geçici ve sakıncalı bir parçasıdır. Daha fazla geçici eklentiler eklemek dili zorlaştırır. Bunun yerine, GHC son zamanlarda generic deriving için destek aldı.

+1

Eh, "türetme" olarak ad-hoc olarak, onlar gücünü genişletmeye devam ettik. Yine, 'Monoid' türetmek için alternatif mekanizmalar olduğunu biliyorum; Bunun yerine, 'DeriveFunctor' (ve diğerleri)' nin neden var olduğunu, DeriveMonoid'in (ve başkalarının) neden olmadığını soruyorum. Bu sadece keyfi mi? – mergeconflict

+2

Sonuçta bu keyfi, ancak önerilen uzantı çok daha az yararlı görünüyor. Çoğu funktöre hizmet etmek için özel bir dil özelliği bana iyi geliyor. Ürün tekstillerine hizmet etmek için özel bir dil özelliği, eklemeye izin vermeyecek kadar az gibi görünüyor. Kapsam hakkında düşünmeniz gerekir (eğer 'Monoid' sonra başka sınıflar?). Yararlı tekeller genellikle yeni tip sarmalayıcıları kullanırlar. Bu nedenle, türetme formunu kullanmak için T = T (Toplam Tamsayı) (Endo Char) 'veri yazarsınız, bu da çirkin bir kullanımdır (iç içe yapıcılarla eşleşmesi gerekir). – sdcvvc

+2

Özet türleri olan çok sayıda yararlı mono malzeme vardır, ancak bu uygulama örneklerinden herhangi birini türetemez.= ( –