2015-12-04 28 views
6

Bu unvanın çok açıklayıcı olmadığını kabul etmekteyim, ancak bunun kısa bir başlıkta nasıl tanımlanacağını bilmiyorum. Önerileri takdir ediyorum! Benim konuyla :)Genel bir sınıflandırma örneğini bir dizi küçükten mi ayırdınız?

çok basitleştirilmiş bir sürümünü sunmak için gidiyorum

Yani belirli bir kanonik yapımını oluşturmak mümkün olması gerekiyordu bir typeclass

class Known f a where 
    known :: f a 

var GADT'ler ve diğer şeyler ile çalışmak için yararlı olan belirli bir dizine yazın. İlgili parçalar ile this'un basitleştirilmiş bir versiyonunu veriyorum.

instance Known Proxy a where 
    known = Proxy 

kullanabileceğimiz:

Yani belli Proxy için bir örnek var

> known :: Proxy Monad 
Proxy 

Ama this HList-like type için bir örnek de var:

data Prod f :: [k] -> * where 
    PNil :: Prod f '[] 
    (:<) :: f a -> Prod f as -> Prod f (a ': as) 

infixr 5 (:<) 

Nerede bir Prod f '[a,b,c] ediyorum kabaca'e eşit olmaktuple. Aynı Functor, farklı tipler. örneğini Yazma

terbiyeli basittir:

> known :: Prod Proxy '[1,2,3] 
Proxy :< Proxy :< Proxy :< PNil 

Ama ben yapmak gerekir durumunda değilim (bir gösterin örneği varsayarak): Oldukça iyi çalışıyor

instance Known (Prod f) '[] where 
    known = PNil 
instance (Known f a, Known (Prod f) as) => Known (Prod f) (a ': as) where 
    known = known :< known 

Tüm as'da bir "polimorfik" fonksiyon ... ama GHC bunu beğenmiyor.

asProds :: forall as. Proxy as -> Prod Proxy as 
asProds _ = known :: Prod Proxy as 

Bu hata ile çıkageldi:

Ben GHC o herhangi as için çalışacak bulacaktır bir örnek olacağını göstermez söyleyerek sanırım
No instance for (Known (Prod f) as) 
    arising from a use of 'known' 

, veya bu örnek için known oluşturmak için bir stratejisi yoktur.

İnsan olarak bunun böyle olduğunu biliyorum, ancak bunu işe alabilmek için herhangi bir yol var mı? Örneklerin hepsi "kapsamda" ve mevcut ... ama GHC'ye nasıl tatmin edileceği konusunda nasıl bir şey yapılacağını nasıl anlatabilirim?

cevap

5

Bir sınıf için herhangi bir kısıtlama yoksa, yöntemlerini kullanamazsınız.

tipleri silinir olduğundan
asProds (_ :: Proxy as) = known :: Prod Proxy as 
-- inferred constraint 

, orada hiçbir şey örnekleri ile başlamak için bir sözlüğe yokluğunda çalışma zamanını inşa edilebileceğini hangi: GHC bu tip anlaması anlamına

asProds :: forall as. Known (Prod Proxy) as => Proxy as -> Prod Proxy as 
asProds _ = known :: Prod Proxy as 

Not: Sadece kısıtlama ekleme .Mantıken doğrudur ki, bir türdeki tüm sakinlere örnekler vardır, ancak programlara ihtiyaç duyduğumuz sözlükler için - yapıcı kanıtlar - koşmak gerekir.

Kısıtlamaların yazılması bizi rahatsız etmemeli, çünkü tüm durumlar için örneklerimiz varsa, bir örneğe gereksinim duyduğumuzda genellikle çok sık olmayan istisnalar elde edebiliriz. Bunun istisnası, tip aile uygulamaları ile açık bir tür için örnek istediğimiz zamandır. Bu durumda, diğer bilinen örneklerden istenen tipte örnekleri açıkça oluşturan işlevler yazmamız gerekir.

+0

Ah. Ne yazık ki, böyle bir kısıtlamadan kaçınmak, öncelikle bunun içinden geçmemin sebebidir. Fakat! Benim problemim başlangıçta tüm varoluşumlarım için '(Applicative (Foo ns), Katlanabilir (Foo ns))' vb. Belirtmek için gerekliydi ve bunun sadece bundan kurtulmasını sağlayabileceğini düşündüm. Ama şimdi görüyorum ki, tüm bu kısıtlamaların tümünü Bilinen bir kısıtlama ile değiştirebiliyorum. Kısıtlamadan sakınmak yok, ama şimdi sadece bir yakalama yapmak çok daha temiz, teşekkürler! –

+0

@JustinL. [Kısıtlama eşanlamlıları] 'nı da kullanabilirsiniz (https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/constraint-kind.html): 'type Known ns = (Applicative (Foo ns)) , Katlanabilir (Foo ns), ...) '. –

+0

@AlexeyRomanov hala bana çok ad-hoc ve un-haskell hissediyor. Tür için gerçek veri yapıcısına ait herhangi bir işin bulunmadığı çok nadir/nadir ve belirsiz kullanımlara sahip bir dizi örnek atabilirim. herşey. Her defasında yeni bir örnek yazdığımda sınıfı ve yinelenen işi eklemem gerekir. –