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