2015-12-04 63 views
6

這個標題確實不是很具描述性,但我不知道如何用簡短的標題來描述這個。我會很感激任何建議!從一系列較小的實例推斷一般類型實例?

我將要提出我的問題:)

的一個非常簡化的版本,所以我有一個類型類

class Known f a where 
    known :: f a 

這被認爲是能夠產生一個給定的規範建設鍵入某個索引,對於使用GADT和其他東西很有用。我給出this的簡化版本以及相關部分。

所以這是很明顯的Proxy一個實例:

instance Known Proxy a where 
    known = Proxy 

,我們可以使用:

> known :: Proxy Monad 
Proxy 

但也有一個爲this HList-like type一個實例:

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

infixr 5 (:<) 

Prod f '[a,b,c]會大致相當於一個(f a, f b, f c)元組。相同的函子,不同的類型。

編寫實例體面簡單:

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

其中一期工程得非常好:(假定顯示實例)

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

但是,我在哪裏,我需要做的情況下所有as上的「多態」功能......但GHC不喜歡它。

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

它與此錯誤出現:

No instance for (Known (Prod f) as) 
    arising from a use of 'known' 

我的猜測是說,GHC無法顯示,將有一個實例它將搭載將爲任何as工作,或者,它沒有爲該實例構建known的策略。

作爲一個人我知道這是事實,但是有什麼辦法可以讓這個工作?這些實例都在「範圍內」並且可用......但我怎麼能告訴GHC如何以滿意的方式構建它?

回答

5

如果對類沒有限制,則不能使用它的方法。只需添加約束:

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

注意GHC可以推斷該類型:

asProds (_ :: Proxy as) = known :: Prod Proxy as 
-- inferred constraint 

因爲類型擦除,並沒有什麼東西哪些實例可以構建運行在沒有字典的開始與。在所有的居民中都存在這樣的情況,但對於我們需要字典的程序 - 建設性證明 - 來說,這在邏輯上是正確的。

寫出約束不應該太麻煩,因爲如果我們有所有情況下的實例,那麼當我們需要一個實例時,通常我們可以得到一個,而不是太頻繁的例外。當我們想要一個具有類型系列應用程序的開放類型的實例時例外。在這種情況下,我們必須編寫函數,從其他已知實例中以所需類型顯式構建實例。

+0

啊。不幸的是,避免這種限制是我首先經歷這個問題的原因。但!我的問題最初是因爲我需要爲我所有的存在指定'(Applicative(Foo ns),Foldable(Foo ns))'等等,我認爲只有這樣才能擺脫這一切。但我現在看到,我可以用'已知'約束替換所有這些各種約束。沒有避免這種限制,但現在只需要一個全部更清潔,謝謝! –

+0

@JustinL。你也可以使用[約束同義詞](https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/constraint-kind.html):'type Known ns =(Applicative(Foo ns) ,可摺疊(Foo ns),...)'。 –

+0

@AlexeyRomanov它仍然感覺非常臨時和un-haskell給我。我可能會拋出一堆實例,這些實例只有非常罕見/不常見和晦澀的用法,這些用法在實際的數據構造函數中沒有任何業務屬於這種類型......它與那些晦澀難懂的類沒有任何關係所有。每次我寫一個新的實例時,我都必須添加類和重複的工作。 –