2017-06-16 3 views
2

は、私は単純なリストのタイプを定義した:typeclassではなくconcrete型の `instance`ですか?

data MyList a = End 
       |Entry a (MyList a) 

私は明示的に自分のすべてMyList aaについてはShowのインスタンスであることを実装する代わりにderiving (Show)の。

instance Show a => Show (MyList a) 
    where show End = "" 
     show (Entry a l) = (show a) ++","++(show l) 

これは完全に問題なく動作します。今、私はそのようなMyList StringだけではShowのインスタンスであることを変更すると、私は

instance Show (MyList String) 
    where show End = "" 
     show (Entry a l) = a ++","++(show l) 

を書いたので、やってみたかった。しかし、これは私が理解していないこと、エラーが発生しました:

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

ことができます誰にもなぜこれがうまくいかず、このエラーが私に何を伝えているのか説明してください。

答えて

3

標準のHaskellでは、この種のインスタンス定義が許可されていないというエラーが表示されています。

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. 

が理由の一つは、場合には、あなたのインスタンス定義の両方を残すことで、正確に、それが言うように、コンパイラは、それらの両方の一致として、MyList Stringのために選択するかを知ることができません。

インスタンスタイプの形式にこの制約を設定すると、型チェックが常に終了することが保証されます。また、この形式以外のインスタンスを持つ有効な型チェック可能なプログラムが存在することが保証されます(ただし、rules for overlapping instancesを参照することもできます)。 、それはちょうどそれが働く方法です:Haskellのいくつかの制限は控えめです。

特定のケースでは、コンパイラの示唆(すなわちFlexibleInstancesを有効にする)を行うだけでトリックが行われ、この拡張は終了の点で安全です。

+0

'FlexibleInstances'を有効にしないと、私はタイプメガネ全体で' show'を意味することができますが、特定のタイプではできません。 – flawr

+0

型コンストラクタ(例えばあなたの 'MyList :: * - > *')では 'MyList a'という形式の全体の"型のファミリ "に対してのみクラス(例えば' Show')しか実装できません。 'MyList String'や' MyList Bool'のような特定の個人に依存します。 – kirelagin

+0

ところで、これはまさにショーがハッキー['showList'](https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:showList)を持っている理由です) 方法。 'Char'のリストを他のすべての型のリストとは違って表示したいのですが、標準のHaskellでは' Show [Char] 'インスタンスを実装するだけではいけません。 – kirelagin

関連する問題