10

次のクラスがあるとします。

class P a where
  nameOf :: a -> String

このクラスのすべてのインスタンスが自動的に のインスタンスになることを宣言したいと思いますShow。私の最初の試みは次のとおりです。

instance P a => Show a where
  show = nameOf

昨日、この方法を最初に試みた結果、言語拡張のウサギの群れが発生しました。最初に柔軟なインスタンスをオンにするように言われ、次に決定不能なインスタンスをオンにするように言われ、次にインスタンスをオーバーラップさせ、最後にインスタンス宣言のオーバーラップに関するエラーが発生しました。私はあきらめて、コードの繰り返しに戻りました。ただし、これは基本的に非常に単純な要求のように思われ、簡単に満たされるはずです。

だから、2つの質問:

  1. 私が見逃したばかりの簡単な方法はありますか?
  2. 重複インスタンスの問題が発生するのはなぜですか? パターソンの条件に違反しているように見えるので、なぜ が必要なのかがわかりUndecidableInstancesますが、ここには重複するインスタンスはありません。 のインスタンスPさえありません。Show Doubleタイプチェッカーは、 (このおもちゃの例の場合のように)の複数のインスタンスがあると考えるのはなぜですか?
4

1 に答える 1

5

Pのインスタンスの一部に の他のインスタンスが含まれている可能性がありShow、コンパイラがどのインスタンスを使用するかを決定できないため、インスタンスの重複エラーが発生します。Pforのインスタンスがある場合は、forDoubleの 2 つのインスタンスを取得します。一般的なインスタンスと、Haskell の基本ライブラリで既に宣言されているインスタンスです。このエラーがどのようにトリガーされるかは、質問へのコメントで @augustss によって正しく述べられています。詳細については、仕様を参照してください。ShowDouble

既にご存じのとおり、UndecidableInstances. そのフラグを有効にすると、競合するインスタンスが発生しないようにするためにコンパイラの責任を引き継ぐことを理解する必要があります。Showこれは、もちろん、あなたのライブラリに他の生成されたインスタンスがあってはならないことを意味します。これは、ライブラリがクラスをエクスポートしないことも意味します。これPにより、ライブラリのユーザーが競合するインスタンスを宣言する可能性がなくなります。

あなたのケースが上記と矛盾する場合は、何か問題があるに違いないという信頼できる兆候です。そして実際には...


あなたが達成しようとしていることは、何よりも間違っています。型クラスに関するいくつかの重要な点が欠けており、一般的な OO 言語のメソッドのShowような構造とは区別されます。toString

  1. ショーのハドックから:

    show の結果は、型が宣言された時点で有効な固定宣言が与えられているため、定数のみを含む構文的に正しい Haskell 式です。これには、データ型、括弧、およびスペースで定義されたコンストラクター名のみが含まれます。ラベル付きのコンストラクター フィールドが使用される場合、中かっこ、コンマ、フィールド名、および等号も使用されます。

    言い換えるとShow、有効な Haskell 式を生成しない のインスタンスを宣言すること自体が正しくありません。

  2. Show上記を考えると、型が単純に派生できる場合のカスタムインスタンスを宣言することは意味がありません。

  3. 型が派生を許可しない場合 (GADT など)、通常、正しい結果を生成するには、型固有のインスタンスに固執する必要があります。

したがって、カスタム表現関数が必要な場合は、そのために使用Showしないでください。カスタム クラスを宣言するだけです。

class Repr a where
  repr :: a -> String

責任を持ってインスタンス宣言に取り組みます。

于 2013-04-04T15:29:18.407 に答える