2015-10-14 29 views
6

Bir türüm var (ara A) ve A -> A, A -> türlerinin fonksiyonlarını yazmak istiyorum A -> A, A -> A -> A -> ... vs Bu işe yaramazsa:Haskell - Bütün fonksiyonlar A -> A -> ... -> A

{-# LANGUAGE FlexibleInstances #-} 

data A = A 

class AsToA a where 
    takeA :: AsToA b => a -> A -> Either A b 

instance AsToA (A -> A) where 
    takeA f a = Left (f a) 

instance AsToA b => AsToA (A -> b) where 
    takeA f a = Right (f a) 

aşağıdaki hata iletisi alıyorum:

AsToA.hs:12:22: 
    Couldn't match expected type ‘b1’ with actual type ‘b’ 
     ‘b’ is a rigid type variable bound by 
      the instance declaration at AsToA.hs:11:10 
     ‘b1’ is a rigid type variable bound by 
      the type signature for 

      takeA :: AsToA b1 => (A -> b) -> A -> Either A b1 
      at AsToA.hs:12:3 
    Relevant bindings include 
     f :: A -> b (bound at AsToA.hs:12:9) 
     takeA :: (A -> b) -> A -> Either A b1 (bound at AsToA.hs:12:3) 
    In the first argument of ‘Right’, namely ‘(f a)’ 
    In the expression: Right (f a) 

Herhangi bir fikir? Herhangi bir tavsiye için çok teşekkürler. İki b s arasında bir karışıklık vardır

+0

Ben takeA' örtülü varoluşsal ölçülür 'yüzünden olduğunu% 90 eminim. –

cevap

2

, gerçekten Either gerekmeyebilir ve takeA sadece bir tür kısıtlama, daha sonra temelde hep id olduğunu. bu yüzden bu bir yöntem daha az sınıf yapabiliyorsanız:

{-# LANGUAGE FlexibleInstances, FlexibleContexts #-} 

data A = A 

class AsToA a 

takeA :: AsToA a => a -> a 
takeA = id 

instance AsToA (A -> A) 

instance AsToA (A -> b) => AsToA (A -> (A -> b)) 

Alternatif olarak, dinamik A s geçmesine izin veren bir ortak türüne dönüştürmek fonksiyonları isteyebilirsiniz.böylece Either yeterli olmayacak, ancak kendi tanımlayabilirsiniz ise:

{-# LANGUAGE FlexibleInstances, FlexibleContexts #-} 

data A = A 

data R = Result A | MoreArgs (A -> R) 

class AsToA a where 
    takeA :: a -> A -> R 

instance AsToA (A -> A) where 
    takeA f a = Result (f a) 

instance AsToA (A -> b) => AsToA (A -> (A -> b)) where 
    takeA f a = MoreArgs (takeA $ f a) 
+0

Bu ikinci cevap mükemmel, çok teşekkürler. Daha önce çok açık olmasaydım özür dilerim. – RhubarbAndC

4

:

class AsToA a where 
    takeA :: AsToA b => a -> A -> Either A b 

instance AsToA b => AsToA (A -> b) where 
    takeA f a = Right (f a) 

Bunlar aynı değildir. en Either A b türünde olup, Right (f a) Şimdi c

class AsToA a where 
    takeA :: AsToA c => a -> A -> Either A c 

instance AsToA b => AsToA (A -> b) where 
    takeA f a = Right (f a) 

ilk kişinin adlandırmak ama AsToA c tutan böyle herhangi c için türünü Either A c olmalıdır edelim. Bu, yazmaz. Burada

sorunu olduğunu takeAherhangic, arayanın seçim için Either A c dönebilmek imza

takeA :: AsToA c => a -> A -> Either A c 

vaat. İstediğin bu değil galiba.


Asıl amaçlanan sonucun ne olduğundan emin değilim, ama sanırım sorun aşağıdaki olana benzer.

(dolayısıyla tip A->A arasında) türü, her -> için x bir uygulama ile, bir işlev \x -> f x x ... geri A->A->...->A tipte bir fonksiyonu f Verilen.

Muhtemel bir çözüm oldukça kötü kullanılacak olan bu OverlappingInstances gerektirir

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-} 
data A = A -- could be anything 

class C f where 
    takeA :: f -> A -> A 

instance C (A -> A) where 
    takeA f = f 

instance C b => C (A -> b) where 
    takeA f = \x -> takeA (f x) x 

Not vardır. Bunu önlemek için tavsiye ederim.

Bunu önlemek için, bu örnekte tip A için bile bir örnek tanımlamak yeterlidir. Diğer yanıt için yorum belirtildiği gibi

{-# LANGUAGE FlexibleInstances #-} 
data A = A -- could be anything 

class C f where 
    takeA :: f -> A -> A 

instance C A where 
    takeA a = \_ -> a 

instance C b => C (A -> b) where 
    takeA f = \x -> takeA (f x) x 
+1

*, TakeA'nın herhangi bir c * için A'dan c'ye geri dönebileceğine dair söz verir - bu nedenle, 'takeA' 'forall b olarak bildirilmesi problemidir. AsToA b = a -> a -> Ya A b', örneğinde "b" sert, doğru mu? –

+0

Peki ne yaptığımı önerirsiniz? Bu typeclass'ı tanımlamak mümkün mü? – RhubarbAndC

+1

@RhubarbAndC Tam olarak –

İlgili konular