重叠多参数实例和实例特异性

问题描述 投票:0回答:2
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
module OverlappingSpecificsError where

class EqM a b where
    (===) :: a -> b -> Bool

instance {-# OVERLAPPABLE #-} Eq a => EqM a a where
    a === b = a == b

instance {-# OVERLAPPABLE #-} EqM a b where
    a === b = False

aretheyreallyeq :: (Eq a, Eq b) => Either a b -> Either a b -> Bool
aretheyreallyeq (Left a1) (Right b2) = a1 == b2

aretheyeq :: (Eq a, Eq b) => Either a b -> Either a b -> Bool
aretheyeq (Left a1) (Right b2) = a1 === b2

aretheyreallyeqaretheyeq都没有编译,但是aretheyreallyeq的错误对我来说很有意义,并且还告诉我aretheyeq不应该给出错误:GHCi建议的一种情况可能适用于EqM由于aretheyeq上的相同错误,因此aretheyreallyeq中的]应该是不可能的。发生了什么事?

重点是,GHCi坚持认为EqM的两个实例都适用于aretheyeq。但是a1的类型为ab2的类型为b,因此,为了使第一个实例适用,必须将ab的类型统一。

但是这不可能,因为它们在函数签名处被声明为类型变量(也就是说,使用第一个EqM实例将导致该函数的类型为Either a a -> Either a a -> Bool,并且错误发生在[C0 ]告诉我,GHCi不允许这样做(这也是我所期望的)。

我是否丢失了某些东西,或者这是一个如何检查具有多参数类型类的重叠实例的错误?

[我想也许与以下事实有关:aretheyreallyeqa可以稍后在b之外,再实例化到相等的点,然后是第一个实例有效吗?但是aretheyeq也是如此。唯一的区别是,如果他们不统一,我们可以选择aretheyreallyeq,但不能选择aretheyeq。无论如何,Haskell出于许多充分而显而易见的原因而没有动态调度,因此,不管以后aretheyreallyeqa是否无法执行,提交将使always起作用的实例的恐惧是什么? ?也许有某种表达方式可以使调用函数时以某种方式选择实例?

值得注意的是,如果删除第二个实例,则该函数显然仍无法编译,并指出找不到任何实例b。因此,如果我没有该实例,那么没有一个起作用,但是当那个实例起作用时,突然另一个实例也起作用,并且我有重叠吗?几英里外的我对我来说像臭虫。

haskell typeclass overlapping-instances multiparameter
2个回答
0
投票

通用变量上的实例匹配以这种方式工作,以防止出现某些可能造成混淆(和危险)的情况。


-1
投票
aretheyeq :: EqM a b => Either a b -> Either a b -> Bool 失败,因为作用域中有两个不同的类型变量。在

aretheyreallyeq

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