各种“..Instances”编译指示如何协同工作,是否有解决我当前问题的方法?
How do the various "..Instances" pragma's work together, and is there a way around my current problem?
考虑以下代码:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
class X a
class Y a
instance Y Bool
instance (Y a) => X a
instance {-# OVERLAPPING #-} X Int
f :: (X a) => a -> a
f x = x
编写上述实例需要这些 LANGUAGE pragma。
现在,假设我们要编写一个函数 g:
g :: (Y a) => a -> a
g = f
没有 IncoherentInstances 或向其中一个实例添加 {-# INCOHERENT #-},这不会进行类型检查。
但是当我们添加这个,并询问 ghci
ghci> :t f
f :: Y a => a -> a
'f' 的类型突然改变了?
对于这个小例子,当我给 f 一个 Int 时,程序仍然会进行类型检查(表明上面只是一个 'visual bug',但在一个更大的例子中,它不会进行类型检查,给我一个错误:
Could not deduce (Y a) arising from a use of 'f
(...)
from the context: (..., X a, ...)
当我们说
时也会发生这种情况
h = f
并尝试用 Int
调用 h
:type f
不报告已定义实体的类型 f
。它报告表达式 f
的类型。 GHC 非常努力地从表达式中去除多态性。特别是,在表达式中使用 f
会触发 X a
约束的简化(就像使用任何带约束的定义一样)。如果没有 IncoherentInstances
,GHC 会避免使用 instance Y a => X a
,因为还有另一个实例与它重叠,因此 GHC 需要等待,看看它应该使用哪个。这确保了连贯性; only X Int
曾经使用过的实例是明确的 "specialized" 实例。使用 IncoherentInstances
,你说你不关心连贯性,所以只要 f
出现在表达式中,GHC 就会继续使用多态实例将 X a
简化为 Y a
。您看到的奇怪行为有时 GHC 可以使用 X Int
有时抱怨没有 Y Int
是 GHC 对何时要简化约束做出不同的内部决定的结果(您确实要求不连贯!)。查看定义类型的命令是:type +v
。 :type +v f
应该显示 f
"as declared" 的类型。希望您也能看到 IncoherentInstances
是个坏主意。不要使用它。
考虑以下代码:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
class X a
class Y a
instance Y Bool
instance (Y a) => X a
instance {-# OVERLAPPING #-} X Int
f :: (X a) => a -> a
f x = x
编写上述实例需要这些 LANGUAGE pragma。
现在,假设我们要编写一个函数 g:
g :: (Y a) => a -> a
g = f
没有 IncoherentInstances 或向其中一个实例添加 {-# INCOHERENT #-},这不会进行类型检查。 但是当我们添加这个,并询问 ghci
ghci> :t f
f :: Y a => a -> a
'f' 的类型突然改变了?
对于这个小例子,当我给 f 一个 Int 时,程序仍然会进行类型检查(表明上面只是一个 'visual bug',但在一个更大的例子中,它不会进行类型检查,给我一个错误:
Could not deduce (Y a) arising from a use of 'f
(...)
from the context: (..., X a, ...)
当我们说
时也会发生这种情况h = f
并尝试用 Int
调用 h:type f
不报告已定义实体的类型 f
。它报告表达式 f
的类型。 GHC 非常努力地从表达式中去除多态性。特别是,在表达式中使用 f
会触发 X a
约束的简化(就像使用任何带约束的定义一样)。如果没有 IncoherentInstances
,GHC 会避免使用 instance Y a => X a
,因为还有另一个实例与它重叠,因此 GHC 需要等待,看看它应该使用哪个。这确保了连贯性; only X Int
曾经使用过的实例是明确的 "specialized" 实例。使用 IncoherentInstances
,你说你不关心连贯性,所以只要 f
出现在表达式中,GHC 就会继续使用多态实例将 X a
简化为 Y a
。您看到的奇怪行为有时 GHC 可以使用 X Int
有时抱怨没有 Y Int
是 GHC 对何时要简化约束做出不同的内部决定的结果(您确实要求不连贯!)。查看定义类型的命令是:type +v
。 :type +v f
应该显示 f
"as declared" 的类型。希望您也能看到 IncoherentInstances
是个坏主意。不要使用它。