Desen

2013-02-13 27 views
5

Biz tür * parametreleri için tek, kapsamlı örneklerini yazabilir Tanıtılan Türleri üzerinde Eşleştirme derleyici, herhangi bir Maybe d için eşleşen bir örnek bulduğu için test1.Desen

Hatta tip kurucular sınıf parametreleri için her şeyi kapsayan bir örneğini yazabilir

: derleyici bir bulur, çünkü

class MyClass2 (a :: * -> *) where 
    g :: Tagged (a Int) Int 

instance MyClass2 a where 
    g = Tagged 3 

test2 :: Int 
test2 = untag (g :: Tagged (Maybe Int) Int) 

Bu aynı zamanda iyi derler ve dnm2 bir (sinif2 Belki) kısıtlamasını ihtiyacı yoktur eşleme örneği.

{-# LANGUAGE TypeOperators, 
DataKinds, 
KindSignatures, 
GADTs, 
FlexibleInstances, 
FlexibleContexts, 
ScopedTypeVariables #-} 

import Data.Tagged 
import Data.Proxy 

data HList :: [*] -> * where 
       HNil :: HList '[] 
       HCons :: a -> HList as -> HList (a ': as) 

class ListLen a where 
    len :: Tagged a Int 

instance ListLen (HList '[]) where 
    len = Tagged 0 

instance (ListLen (HList as)) => ListLen (HList (a ': as)) where 
    len = Tagged (1+(untag (len :: Tagged (HList as) Int))) 

test3 :: Int 
test3 = untag (len :: Tagged (HList '[Int, Double, Integer]) Int) 

test4 :: (Proxy (HList qs)) -> Int 
test4 (_ :: Proxy (HList qs)) = untag (len :: Tagged (HList qs) Int) -- error occurs here 

Bu hata ile sonuçlanır:

aşağıdaki oyuncak kodu (tanıtılan) uzunluğunu hesaplamak listesini yazmak için düşünün

No instance for (ListLen (HList qs)) 
     arising from a use of `len' 
    Possible fix: add an instance declaration for (ListLen (HList qs)) 
    ... 

biz test4 için imza açıklama ise GHCi, türü

olarak tanımlamaktadır. Bu gerekli olmamalıdır. Açıkça, herhangi bir akla gelebilecek tipte liste ile eşleşen ListLen için örnekler yazdım: bir 'boş liste' durumu ve bir 'eksiler' durumu. türünün türünü [*] türüne göre değiştirdiğimde sorun aynı kalır (yani HList sarıcısını ListLen ve örneklerinde kaldırın).

biz test4, test3 derler açıklama ve ince çalışıyorsa: I (esasen) burayı ben Tür listesini inşa nasıl açık sözdizimi ( '[Int,Double,Integer]) verdi çünkü derleyici eşleşen örneklerini bulmak mümkün oldu.

Benim için bir tür listesi oluşturan kod yazmayı deniyorum, bu yüzden açık tür listesi sözdizimini yazmam gerekmeyecek. Bununla birlikte, açık sözdizimi kullanmak, GHC'nin bu kapsamlı örnekleri eşleştirebilmesinin tek yoludur. Belkide kayıp bir durum var mı? Sözdizimi Kullanmıyorum?

GHC'nin, [*] türünde her şey için bir örneğim olduğunu fark etmesini sağlamak için ne yapabilirim? GHC 7.4.2 kullanıyorum. Bu , numaralı telefonun, previous post ile desteklenmeyen türlerin yapılandırılmasıyla ilgili olabilir. tür tanıtım promosyon here bulunabilir.

+0

Başlık önerileri kabul edilir. – crockeea

+0

* Farklı * örnekleriniz var, nasıl bir tane olsun? GHC örneği seçmeli ve bu parametrik olmayan bir işlemdir, bu yüzden bir kısıtlama gerektirir. Yapmak istediğin şeyin mantıklı olduğunu düşünmüyorum. –

+0

GHC, * örtüşen * örnekleri (bunlar değil) çalışma zamanında açık bir sınıf kısıtlaması (aksi halde çıkarılacak olan) kullanarak bile çözebilir. Niçin uygun zamanlamayı seçmek için çalışma zamanını beklemek zorunda olsa da * her zaman * bir eşleşme olduğunu göremiyorum? Tabii ki, bunu bunu yapmamı rica ediyorum * sağlamaz (ve karşılıksız) sınıf kısıtlaması olmadan, sağlama lüksüne sahip değilim. – crockeea

cevap

2

Bu tam olarak ne istediğinizi değil, ancak oldukça yaklaşıyor.Ben de kısıtlamayı varsa veya Proxy olması gerekir bile (gerekli sınıfının kanıtlarını ihtiva sorun olduğunu

test4 :: (Proxy (HList qs)) -> Int 
test4 (Proxy len) = untag len 

sonuçlanan sonra

data Proxy a where 
    Proxy :: ListLen a => Proxy 

data Proxy a where 
    Proxy :: Tagged a Int -> Proxy a 

ile başlayan tüm mevcut örnekler için örnekler olsa da). Burada, sınıf yöntemi sadece Proxy'da bulunur.

Tamamen farklı bir seçenek, yalnızca bir sınıf sınıfı kullanmamak ve len'u her zamanki gibi uygulamaktır (Data.List.length'dan kopyalanır).

len :: HList a -> Int 
len l = len' l 0 
    where 
    len' :: HList a -> Int -> Int 
    len' HNil a = a 
    len' (HCons _ xs) a = len' xs $! a + 1