2014-06-18 44 views
2

我在哪裏編寫了下面的代碼,Haskell不會編譯。爲什麼「實例Monad(Gang String)」編譯錯誤

data Gang b a=Gang{getGang::(a,b)} 
instance Monad (Gang String) where 
    return x  = Gang (x,"") 
    (Gang(x,log)) >>=f = let Gang(x1,log1)= f x in Gang(x1,log++log1) 

編譯器輸出:

Illegal instance declaration for `Monad (Gang String)' 
    (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 -XFlexibleInstances if you want to disable this.) 
In the instance declaration for `Monad (Gang String)' 

後,我用 「ghci中-XFlexibleInstances」 推出ghci中並加載文件時,它編譯成功。爲什麼?

+0

嗯...因爲它不是Haskell 98,沒有-X標誌的GHC實現了Haskell 98? –

+0

@ n.m。現在,Haskell 2010實際上就是這樣。這並不是說所有的差別都很大。 –

回答

6

The Haskell Report restricts什麼是不允許出現在類型類的實例(默認)

(第4.3.2節)...類型(T u1 … uk)必須適用於簡單類型變量u1, … uk類型構造T的形式;此外,T不能是一個類型的同義詞,並且ui都必須是不同的。

是否能把鬆散,實例被允許申請類型構造(不是同義詞,所以像ListMaybe甚至零元的像Int),只要傳遞給構造所有的參數都是獨一無二的類型變量。

對你而言,Gang是一個類型構造函數,但String不是一個類型變量。它甚至不是一個類型構造函數!它是具體類型[Char]的類型同義詞。

事實證明,這是過度限制。放鬆對所有傳遞參數的需求是變量是有意義的。允許類型同義詞甚至是有意義的。但是,由於這些鬆弛不是標準化的,因此要求您通過LANGUAGE編譯標記或編譯器標誌來指示您使用非標準擴展。

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-} 

通常,這些附註註釋非常可取,因爲非標準Haskellisms的使用位於特定文件中。你也可以保留所需的Haskell擴展的指示。

+2

['TypeSynonymInstances'由'FlexibleInstances']隱含(http://www.haskell.org/ghc/docs/latest/html/users_guide/flag-reference.html#idp14615552)。 (有些東西告訴我列表並沒有給出所有的含義,有沒有完整的列表?) –

+0

說實話,我總是等到GHC告訴我我需要他們:) –