假设我们有以下代码,其中有两种类型最终放在另外两种类型中,其中最外面的是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
Run Code Online (Sandbox Code Playgroud)
现在,写作[WrapperType SomeType1]给了我想要的东西:
*MyModule> [WrapperType SomeType1]
[correct]
Run Code Online (Sandbox Code Playgroud)
但是一旦我把它放进去,ListWrap我就会选择错误的Show实例来显示内容:
*MyModule> ListWrap [WrapperType SomeType1]
ListWrap [incorrect]
Run Code Online (Sandbox Code Playgroud)
必须有类型类和/或GADT的东西我无法理解 - 它可能是什么?
如果您查看派生代码(with -ddump-deriv),那么您可以看到派生实例ListWrap非常正常
instance Show ListWrap where
showsPrec a (ListWrap b) =
showParen (a >= 11) $ showString "ListWrap " . showsPrec 11 b
Run Code Online (Sandbox Code Playgroud)
它只是将内部表演showsPrec再次传递给他们.这表明问题是d当你使用ListWrap包装它时GHC正在擦除类型变量.事实上,你也可以写ListWrap为
data ListWrap where
ListWrap :: forall d. [(WrapperType d)] -> ListWrap
Run Code Online (Sandbox Code Playgroud)
强调这是存在型的.
我们可以通过删除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.
Run Code Online (Sandbox Code Playgroud)
换句话说,它已经失去了关于d类型的细节,因此无法统一具体instance Show (WrapperType SomeType1).
现在你会认为这意味着保持这种类型信息会使类型错误消失.
data ListWrap d where
ListWrap :: [(WrapperType d)] -> ListWrap d
> show $ ListWrap [WrapperType SomeType1]
"ListWrap [incorrect]"
Run Code Online (Sandbox Code Playgroud)
但似乎实例搜索也出错了.我能找到使其工作的唯一方法是打开UndecidableInstances并提供实例推导的建议.
deriving instance Show (WrapperType d) => Show (ListWrap d)
Run Code Online (Sandbox Code Playgroud)
之后该示例有效
> show $ ListWrap [WrapperType SomeType1]
"ListWrap [correct]"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
133 次 |
| 最近记录: |