如何让GHC为上下文中具有Typeable的GADT生成Data.Typeable实例?

yat*_*975 7 haskell ghc derived-instances gadt

假设我有以下代码:

{-# LANGUAGE GADTs, DeriveDataTypeable, StandaloneDeriving #-}
import Data.Typeable

class Eq t => OnlyEq t
class (Eq t, Typeable t) => BothEqAndTypeable t

data Wrapper a where
    Wrap :: BothEqAndTypeable a => a -> Wrapper a

deriving instance Eq (Wrapper a)
deriving instance Typeable1 Wrapper
Run Code Online (Sandbox Code Playgroud)

然后,以下实例声明工作,没有约束t:

instance OnlyEq (Wrapper t)
Run Code Online (Sandbox Code Playgroud)

并做我期望它做的事情.


但是以下实例声明不起作用:

instance BothEqAndTypeable (Wrapper t)
Run Code Online (Sandbox Code Playgroud)

自GHC - 我使用7.6.1 - 抱怨说:

No instance for (Typeable t)
  arising from the superclasses of an instance declaration
Possible fix:
  add (Typeable t) to the context of the instance declaration
In the instance declaration for `BothEqAndTypeable (Wrapper t)'
Run Code Online (Sandbox Code Playgroud)

Typeable t当然,添加到上下文工作.但添加以下实例也是如此:

instance Typeable (Wrapper t) where
    typeOf (Wrap x) = typeOf1 (Wrap x) `mkAppTy` typeOf x
Run Code Online (Sandbox Code Playgroud)

有没有办法让GHC为我写这个后一个实例?如果是这样,怎么样?如果没有,为什么不呢?

我希望GHC能够TypeableWrap构造函数的上下文中拉出约束,就像它对Eq约束一样.我认为我的问题归结为GHC明确禁止写作这一事实deriving instance Typeable (Wrapper t),而标准(Typeable1 s, Typeable a) => Typeable (s a)实例无法"查找内部" s a来查找Typeable a字典.

Dan*_*her 5

我希望GHC能够TypeableWrap构造函数的上下文中拉出约束

如果它有一个Wrap构造函数,它可以Typeable从中拉出约束.

但它没有Wrap构造函数.

不同之处在于Eq实例使用了值,所以它是a Wrap something,Wrap构造函数使得Eq包装类型的字典可用,一切都很好,或者它是?,然后一切都很好,评估x == y底部.

注意派生

instance Eq (Wrapper a)
Run Code Online (Sandbox Code Playgroud)

不能有一个Eq对类型变量的约束a.

Prelude DerivT> (undefined :: Wrapper (Int -> Int)) == undefined
*** Exception: Prelude.undefined
Prelude DerivT> (undefined :: (Int -> Int)) == undefined

<interactive>:3:29:
    No instance for (Eq (Int -> Int)) arising from a use of `=='
    Possible fix: add an instance declaration for (Eq (Int -> Int))
    In the expression: (undefined :: Int -> Int) == undefined
    In an equation for `it':
        it = (undefined :: Int -> Int) == undefined
Run Code Online (Sandbox Code Playgroud)

但是Typeable实例不能使用该值,因此如果提供的值不是a,则不会触底Wrap something.

因此衍生的instance Typeable1 Wrapper供应

instance Typeable t => Typeable (Wrapper t)
Run Code Online (Sandbox Code Playgroud)

但不是不受约束的

instance Typeable (Wrapper t)
Run Code Online (Sandbox Code Playgroud)

并且GHC不能导出无约束的实例.

因此,您必须提供约束

instance Typeable t => BothEqAndTypeable (Wrapper t)
Run Code Online (Sandbox Code Playgroud)

或者不受限制的

instance Typeable (Wrapper t)
Run Code Online (Sandbox Code Playgroud)

你自己.

  • 好吧,这是一个有点令人惊讶的例子,因为你不能像其他`Typeable`实例一样使用`undefined :: Wrapper Bool`.如果你公之于众,至少要对它发出警告.但我认为这不一定会阻止你.然而,在未来的GHC版本中 - 从7.8开始,所有`Typeable`实例将由GHC提供,并且对于所有类型,iirc.所以你不必再处理这些问题了. (2认同)