各种“ ..Instances”编译指示如何协同工作,是否有解决我当前问题的方法?

问题描述 投票:0回答:1

请考虑以下代码:

{-# 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编译指示来编写上述实例。

现在,说我们想编写一个函数g:

g :: (Y a) => a -> a
g = f

没有IncoherentInstances或在其中一个实例中添加{-#INCOHERENT#-},这不会进行类型检查。但是,当我们添加此内容并询问ghci

ghci> :t f
f :: Y a => a -> a

突然改变了'f'的类型?

对于这个小例子,当我给f一个Int时,程序仍然会进行类型检查(表明上面只是一个“视觉错误”,但在更大的例子中,它不会进行类型检查,给我一个类似的错误:

Could not deduce (Y a) arising from a use of 'f
(...)
from the context: (..., X a, ...)
haskell ghc typeclass
1个回答
0
投票

:type f不报告已定义实体f的类型。它报告表达式f的类型。 GHC确实努力将多态性排除在表达式之外。特别是,在表达式中使用f会触发X a约束的简化(就像在约束中使用任何定义一样)。如果没有IncoherentInstances,GHC将拒绝使用instance Y a => X a,因为还有另一个实例与之重叠,因此GHC需要等待以查看应使用哪个实例。这样可以确保连贯性;曾经使用过的only X Int实例是显式的“专用”实例。对于IncoherentInstances,您说的是您并不关心连贯性,因此无论何时X a出现在表达式中,GHC都会继续使用多态实例将Y a简化为f。您会看到奇怪的行为,有时使用X Int可以使GHC正常运行,有时会抱怨没有Y Int是GHC在何时简化约束方面做出了不同的内部决策的结果(您确实要求incoherence] >!)。用于查看definition类型的命令为:type +v:type +v f应该显示f的类型,如“声明的”。希望您也可以看到IncoherentInstances是一个坏主意。不要使用它。

© www.soinside.com 2019 - 2024. All rights reserved.