2012-09-19 7 views
15

Heap türünde * -> * türünde bir kurucu olan Heap a türüne sahip olduğumu varsayalım. Yığın üzerindeki birçok temel işlem, a türünün Ord tür sınıfının bir örneği olmasını gerektirir.Türlü örneklerin türleri için tür sınırlamaları * -> *

data Heap a = ... 

findMin :: Ord a => Heap a -> a 
deleteMin :: Ord a => Heap a -> Heap a 

Ben (findMin ve deleteMin fonksiyonları aracılığıyla ifade etmek kolay olacaktır) en kısa sürede a tür parametresi Ord tip sınıfının bir örneğidir olarak Foldable tipi sınıfının bir örneği olarak benim Heap türü bildirmek istiyorum.

biz Show gibi nazik * tipini gerektiren tip sınıfları konusunu ele alırken ilişkinin Bu tür easely ifade edilebilir:

instance Show a => Show (Heap a) where 
    show h = ... 

Ama elimdeki sorunları bildirimiyle Foldable ait:

instance Foldable Heap where 
    -- Ouch, there is no `a` type parameter to put the constraint on! 
    foldr f z h = ... 

Bu örnek beyanda a tip parametresi üzerinde kısıtlama koymak mümkün mü?

+4

[Bu şeyler] 'e bir göz atın (http://blog.omega-prime.co.uk/?p=127). Monadlarla benzer bir şey yapıyorlar. – phg

+0

Link için çok teşekkür ederim, ConstraintKind' _really_ ilginç şeyler! –

+1

Btw, 'findMin' gerçekten bir' Ord' örneğini gerektirmiyor mu? – yairchu

cevap

17

Genel olarak, hayır, yapıcı türünün kendisine verildiği zaman, uygulandığı türleri kısıtlama yolu yoktur. Çoğunlukla bu iyi bir şeydir, çünkü Functor örnekleri, güzel ve öngörülebilir davranışları güzel ve öngörülebilir tutmaya yardımcı olan, eleman türleriyle ilgili gerçekten agnostiktir.

Bunun yerine bazen bir sıkıntıdır ve en yaygın örnek, güzel, iyi huylu bir örnek olabilecek sıralı bir veri yapısı için Ord kısıtlamasına gereksinim duyar.

Kısıtlama türlerini içeren bazı deneysel teknikler vardır, ancak özel durumunuzda zaten geçerli bir çözüm var. Foldable tanımına bakarsanız, yalnızca foldMap veya foldr'un uygulanması gerektiğini söylüyor, dolayısıyla bunları dikkate alacağız. türlerini Not: Her iki durumda da

foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m 
foldr :: (Foldable t) => (a -> b -> b) -> b -> t a -> b 

, bir Foldable örnekle türü yalnızca işlevine argüman olarak bir kez görünür. Bu nedenle, bir Ord kısıtlaması ile use GADTs edebilirsiniz:

data Heap a where 
    Heap :: (Ord a) => ... 

Bunu yaparak, size Heap değeri, hatta boş bir yığın oluşturmak her zaman bir Ord örneğini gerekir; ancak , değerini Heap değeri aldığınızda, Ord örneğini örneğini Foldable örneğinin içinde bile kapsam içine getirecektir! Bu diğer birçok durumlarda yardımcı olmadığını

Not:

İşte
fmap :: (Functor f) => (a -> b) -> f a -> f b 

biz a bir Ord örneğini alabilirsiniz, ama biz de mümkün değildir ki, b tane gerekiyordu.

return :: (Monad m) => a -> m a 

İşte biz de bir Ord örneğini sağlamanız gerekir.

+0

Teşekkür ederim, çalışıyorum, küçük bir örnek hazırladım: http://ideone.com/HWl7H. Benim için garip görünüyor, ancak bu tür bildirimde yalnızca kısıtlamaları kullanamayız: newtype Ord a => ListHeap a = LH [a] '. Bu yalnızca 'Katlanılabilir' örneği ile çalışmaz. GADTs uzantısını desen eşleştirmesi ile kullanmak zorundayız. Cevabınız için çok teşekkür ederim! –

+0

@ roman-kashitsyn: Evet, düzenli veri türleri için olduğu gibi bir sözdizimi vardı, ama aynı şeyi yapmıyordu ve tamamen işe yaramaz bir yanlış anlaşılmaydı ve muhtemelen dil standardından çıkarılacaktı. ve unuttum). –

0

Hackage'da keys kütüphanesine göz atın. FoldableWithKey tip sınıfının ihtiyacınız olan şey olup olmadığını kontrol edin.