2012-10-25 16 views
6

Bu neden doğru kodBu parametrelenmemiş türle neden bir örnek oluşturamıyorum?

instance Functor IO where -- note that IO isn't parametrized, and it's correct 
    fmap f action = do 
     result <- action 
     return (f result) 

ancak aşağıdaki kod, bir derleyici hatası var mı?

class Print a where 
    print :: a -> String 

data A t = A t 
instance Print A where -- error: expecting one more argument to `A' 
    print a = "abc" 

cevap

10

Bunun nedeni, kinds eşleşmiyor. Normal tipler * türündedir, A veya IO gibi tür yapımcıları ise bir tür döndürmek için bir tür parametresine gereksinim olduğunu belirten * -> * türüne sahiptir.

Print sınıfının tanımında, derleyici, a düz tip olarak kullanıldığından, * türünde olmalıdır. Ancak, tür * -> * tipi yapıcıları üzerinde Functor çalışır:

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

, f düz türü olarak kullanılmaz, ancak bir tür kurucusu olarak, bu tür anlaşılmaktadır oluyor böylece * -> * olduğunu. Sen GHCi içinde :kind komutuyla doğrulayabilirsiniz:

> :kind Print 
Print :: * -> Constraint 
> :kind Functor 
Functor :: (* -> *) -> Constraint 
9

Eğer

class Print a where 
    print' :: a -> String 

Sen a bir tür olmak zorunda olduğundan emin olun, ancak

data A t = A t 

derken sen A bir tür yapıcı yapmak derken - A değil bir tür, ancak A Int, örneğin. A, türlerde bir tür işlevdir, ancak Yazdırma sınıfındaki a, tür işlevi değil, bir tür değeri olmalıdır.

Sen Functor sınıf bir tür kurucusu sorar çünkü IO için Tamam

instance Print (A Int) where 
    print' a = "abc" 

yapabilirdi.

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

Sen f a türüdür beri f sadece IO ve A olduğu gibi, bir tür yapıcı olduğunu görebiliriz. Sen

instance Functor A where -- OK, A is a constructor, Functor needs one 
    fmap f (A x) = A (f x) 

yapmak mümkün olacak ve siz

instance Eq IO where -- not OK - IO is a constructor and Eq needs a type 
    (==) = error "this code won't compile" 

yapmak mümkün olmayacaktır (Ben standart işlevi print diðerbaðlantý önlemek için print' yerine print kullandım.)

1

gelimi kullanılan türle sınıf tanımında verilen tipler doldurarak (veya bir metin editörü ile) zihinsel deneyin.Gönderen

:

class Print a where 
    print :: a -> String 

ve

data A t = A t 

biz bir instnace biz söylüyorsun A için tür sınıf tanımında a yerine,

instance Print A 

Yani

istiyorum Bunu aldık:

Uh-oh. A -> String, tür olarak algılanmaz, çünkü işlev türü ok, solda bir tür ve sağda bir tür alır ve size işlev türünü verir. Ancak A bir tür değil, data A t ile bildirdiğinizden; A t, t türünde bir türdür, ancak A, türünde bir kurucu türüdür. Bir türe uygularsanız bir tür yapabilir, ancak A'un kendisi farklı bir şeydir. A t'u Print'un bir örneğine yapabilir, ancak A'un kendisinde gerçekleştiremezsiniz. O zaman neden instance Functor IO çalıştı? sınıf tanımının bakalım:

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

Şimdi f için IO yerine deneyelim:

class Functor IO where 
    fmap :: (a -> b) -> IO a -> IO b 

IO s uç yukarı parametrelerini yazmak için uygulanan, bu yüzden her şey yoluna girer. Int ya da A t gibi bir somut tipte Functor örneğini denemeye çalışsak, bu problemlerle karşılaşırdık.

İlgili konular