gpt4 book ai didi

haskell - 推断 Eq 类型类

转载 作者:行者123 更新时间:2023-12-04 11:23:14 28 4
gpt4 key购买 nike

我正在编写一个类似 CRUD 的应用程序,并且通过主键进行大量查找(主键可以有不同的类型)。所以我定义了以下类型类:

{-# LANGUAGE MultiParamTypeClasses #-}

class Eq b => HasPK a b where
getPK :: a -> b

现在我可以写:
import Data.Maybe

lookupPK :: HasPK a b => b -> [a] -> Maybe a
lookupPK s = listToMaybe . filter ((== s) . getPK)

现在,当我想用​​PK比较两个东西时,我只想比较他们的PK。所以,我试图定义这个:
{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE UndecidableInstances #-}

instance (HasPK a b) => Eq a where
(==) = (==) `on` getPK

但现在它给了我:
src/Utils.hs:61:10: Could not deduce (HasPK a b0) …
arising from the ambiguity check for an instance declaration
from the context (HasPK a b)
bound by an instance declaration: HasPK a b => Eq a
at /home/utdemir/workspace/.../Utils.hs:61:10-28
The type variable ‘b0’ is ambiguous
In the ambiguity check for: forall a b. HasPK a b => Eq a
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the instance declaration for ‘Eq a’
Compilation failed.

谁能向我解释这个错误?我走在正确的轨道上,还是有更安全的方法来实现我想要的?

最佳答案

你需要一个函数依赖:使用

class Eq b => HasPK a b | a -> b where
getPK :: a -> b

并启用 GHC 指向的任何扩展。

问题在于同一类型有多个 PK 的可能性,
如在
instance HasPK MyType Int where ...
instance HasPK MyType String where ...

由于上面的双实例可以稍后添加,所以像 (==) `on` getPK 这样的代码可能是模棱两可的。确实,在添加上面的实例时,并没有指定是否使用 Int PK 或 String一。

但是,像
instance (HasPK a b) => Eq a where
...

可能会导致问题,因为它与任何其他 Eq 重叠实例。这里要小心。我会改为写
equalPK :: HasPK a b => a -> a -> Bool
equalPK = (==) `on` getPK

然后为所有相关类型提供显式实例,如下所示:
instance Eq MyType1 where (==) = equalPK
instance Eq MyType2 where (==) = equalPK
...

作为另一种选择,您可以使用类型族,例如
class HasPK a where
type PK a
getPK :: a -> PK a

equalPK :: Eq (PK a) => a -> a -> Bool
equalPK = (==) `on` getPK

instance Eq MyType1 where (==) = equalPK
...

关于haskell - 推断 Eq 类型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29028714/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com