2017-06-04 36 views
0

我覺得這應該很容易,但我堅持了很長一段時間。爲數據類型列表創建實例 - Haskell

haskell有可能爲某些數據類型的列表創建一個類型的實例嗎?

我想實現的是以下內容。

class Rename a where 
    findSub :: a -> a 

-- A 'normal' instance would look like this 
instance Rename Atom where 
    findSub ...... 

-- Now i want to acchieve something like this 
instance Rename ([] Atom) where 
    findSub ...... 

當我寫這篇文章如何過我得到以下錯誤:

* Illegal instance declaration for `Rename [Atom]' 
     (All instance types must be of the form (T a1 ... an) 
     where a1 ... an are *distinct type variables*, 
     and each type variable appears at most once in the instance head. 
     Use FlexibleInstances if you want to disable this.) 
    * In the instance declaration for `Rename ([] Atom)' 
Failed, modules loaded: none. 

我想知道如何解決這個問題,爲什麼這是不允許的。

在此先感謝。

回答

3

它只是需要一個語言擴展,因爲這種形式的實例在技術上沒有被Haskell 98標準所允許。當錯誤消息表示啓用擴展時,通常只需執行[1]。 FlexibleInstances是一個非常普遍的接受和推廣,所以只是把

{-# LANGUAGE FlexibleInstances #-} 

在文件的頂部。


另外,很多時候,這種情況下可以「遞歸」規定,在這種情況下你不需要的擴展,但除此之外,你得到免費的多個實例,更保證,因爲類型比較一般。看看你是否可以定義

instance (Rename a) => Rename [a] where 
    findSub ... 

,而不是隻使用一個事實,即aRename,而不是它是具體的Atom。當你可以用這種方式定義實例時,這是一個很好的信號,表明你的設計在正確的軌道上。


[1]有一些例外,如UndecidableInstancesIncoherentInstances,有時表明您對類型類的分辨率是如何工作的一個錯誤的觀念。

+0

我不傾向於看到'UndecidableInstances'出現在錯誤的代碼中;我傾向於在完美的代碼中看到更多,Haskell的極其有限的終止標準不足以證明是好的。 – dfeuer

+0

@dfeuer,一旦你對類型類很熟悉,我同意,但是通常初學者往往會認爲類型類的分辨率倒退或者比它強大得多(例如''實例向量=>數量類'等),這很快導致這些擴展被「需要」(儘管當它們被啓用時它仍然不能按預期工作)。沒有? – luqui

+0

我傾向於更多地考慮'OverlappingInstances','IncoherentInstances','AllowAmbiguousTypes'和(當不使用多參數類型類時)'FlexibleInstances'。但你也許是對的。 – dfeuer