2

私は、次の形式で画面に表示できるようにしたい文字列とタグを含むタプルである、いわゆるトークンを使用しています[TAG: VALUE]。正しいことをしていないため、それを行うことはできません。セットアップは次のとおりです。

type Token value tag = ([value], tag)
data Tag = Whitespace | Alpha | Digit | Punctuation | Terminal
instance Show Tag where
    show Alpha = "A"
    show Whitespace = "W"
    show Digit = "D"
    show Punctuation = "P"
    show Terminal = "|"
type TextToken = Token Char Tag    
instance Show TextToken where
    show (values, tag) = "[" ++ show tag ++ ": " ++ values ++ "]"

コンパイル時にクラッシュするもの:

Illegal instance declaration for `Show TextToken'
  (All instance types must be of the form (T t1 ... tn)
   where T is not a synonym.
   Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Show TextToken'

次に、インスタンスを次のものに置き換えてみました。

instance Show ([Char], Tag) where
   show (values, tag) = "[" ++ show tag ++ ": " ++ values ++ "]"

そして、同じ問題が再び発生しました:

Illegal instance declaration for `Show ([Char], Tag)'
  (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 `Show ([Char], Tag)'

それを機能させる方法はありますか?

4

2 に答える 2

10

あなたはnewtypeを使いたくなるでしょう

newtype Tag a b = Tag (a, b)

instance (Show a, Show b) => Show (Tag a b) where
  show (Tag (a, b)) = "[" ++ show a ++ ": " ++ show b ++ "]"

一度にいくつかのインスタンス解決の問題に直面しています。

  1. プラグマがないと、インスタンス定義でシノニムを{-# LANGUAGE TypeSynonymInstances #-}使用できませんtype...たとえそれらが完全に明確であっても。それを有効にしても問題ありません。単に Haskell 98 ではありません。

  2. インスタンス定義で複雑な型、ネストされた型、またはマルチパラメータ型を使用する場合、過度に制限的な Haskell 98 インスタンス定義に頻繁に違反します。多くの場合、これで問題ないため、{-# LANGUAGE FlexibleInstances #-}プラグマを有効にすると、これらの OK の機会が許可されます。

  3. 最後に、危険なことに、とを持つポリモーフィックな のインスタンスが既に存在します。これは、警告に違反することを意味します。Show([Char], Tag)instance Show (a, b)a ~ [Char]b ~ TagOverlappingInstances

GHCにOverlappingInstances別のプラグマの使用を許可するように指示することでこれを無効にする{-# LANGUAGE OverlappingInstances #-}ことができます.

一般に、インスタンス宣言を特定の型に「特殊化」しようとしている場合は、一般的なケースが存在しない必要があります。

newtype Tup a b = Tup (a, b)

instance Show (Tup Int Int) where
  show (Tup tup) = show tup

instance Show (Tup String Int) where
  show (Tup (s, int)) = s ++ ": " ++ show int

>>> show ("foo", 3)
foo: 3
>>> show (2, 3)
(2, 3)
>>> show ("foo", "bar")
No instance for...
于 2013-11-05T20:00:47.703 に答える
3

本当に決定する必要があるのは、さまざまな種類の .xml に対してさまざまなインスタンスが必要かどうかですToken。その場合は、newtype(またはコンパイラ オプション、いくつかの提案として) を使用します。そうでない場合は、を作成Tokendata、ジェネリックToken型でインスタンスを定義します。

newtypeラッパーを作成するには:

newtype TextToken = TextToken (Token Char Tag)

Show次に、ラッパーのインスタンスを宣言します。

instance Show TextToken where

あなたの場合、私はまだ変更をお勧めします

type Token value tag = ([value], tag)

data Token value tag = Token [value] tag

とにかくレコードタイプがあるため、明示的にすることもできます。

于 2013-11-05T20:06:18.067 に答える