5

次のコードがあるとします。ここでは、いくつかの型が他の 2 つの型の内側に配置されており、その最も外側が GADT です。

{-# LANGUAGE FlexibleInstances,
             GADTSyntax,
             GADTs,
             OverlappingInstances,
             StandaloneDeriving #-}

data SomeType1 = SomeType1 deriving Show
data SomeType2 = SomeType2 deriving Show

class SomeClass d where

instance SomeClass SomeType1 where
instance SomeClass SomeType2 where

data WrapperType t where
  WrapperType :: (SomeClass t, Show t) => t -> (WrapperType t)

instance Show (WrapperType SomeType1) where
  show (WrapperType d) = "correct"

instance Show (WrapperType t) where
  show (WrapperType d) = "incorrect"

data ListWrap where
  ListWrap :: [(WrapperType d)] -> ListWrap

deriving instance Show ListWrap

今、書くこと[WrapperType SomeType1]は私が欲しいものを私に与えます:

*MyModule> [WrapperType SomeType1]
[correct]

しかし、それを中に入れるとすぐに、コンテンツを表示するListWrapために間違ったShowインスタンスが選択されます。

*MyModule> ListWrap [WrapperType SomeType1]
ListWrap [incorrect]

型クラスや GADT について、私が理解できていない何かがあるに違いありません。

4

1 に答える 1

5

派生コード ( を使用-ddump-deriv) を見ると、 の派生インスタンスListWrapがかなり正常に見えることがわかります。

instance Show ListWrap where
  showsPrec a (ListWrap b) =
    showParen (a >= 11) $ showString "ListWrap " . showsPrec 11 b

内側のショーをshowsPrecもう一度渡すだけです。dこれは、ListWrap でラップするときに、GHC が型変数を消去していることに問題があることを示唆しています。ListWrap実際、次のように書くこともできます

data ListWrap where
  ListWrap :: forall d. [(WrapperType d)] -> ListWrap

これは、これが存在的に型付けされていることを強調しています。

instance Show (WrapperType t)を削除してGHC の型エラーを観察することで、エラーをより直接的に見ることができます。

/Users/tel/tmp/foo.hs:33:52: Warning:
    No instance for (Show (WrapperType d))
      arising from a use of `showsPrec'
    Possible fix:
      add an instance declaration for (Show (WrapperType d))
    In the second argument of `(.)', namely `showsPrec 11 b'
    In the second argument of `($)', namely
      `showString "ListWrap " . showsPrec 11 b'
    In the expression:
      showParen (a >= 11) $ showString "ListWrap " . showsPrec 11 b
Ok, modules loaded: Main.

つまり、d型に関する詳細が失われているため、特定の を統一できませんinstance Show (WrapperType SomeType1)


これは、その型情報を維持することで型エラーがなくなることを意味すると考えるでしょう。

data ListWrap d where
  ListWrap :: [(WrapperType d)] -> ListWrap d

> show $ ListWrap [WrapperType SomeType1]
"ListWrap [incorrect]"

しかし、インスタンス検索もうまくいかないようです。それを機能させるために私が見つけた唯一の方法は、オンにしUndecidableInstancesてインスタンス派生の提案を提供することでした。

deriving instance Show (WrapperType d) => Show (ListWrap d)

その後、例が機能します

> show $ ListWrap [WrapperType SomeType1]
"ListWrap [correct]"
于 2013-07-30T22:50:36.977 に答える