首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >推导方程类型

推导方程类型
EN

Stack Overflow用户
提问于 2015-03-13 09:26:13
回答 1查看 96关注 0票数 7

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

代码语言:javascript
复制
{-# LANGUAGE MultiParamTypeClasses #-}

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

现在我可以写了:

代码语言:javascript
复制
import Data.Maybe

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

现在,当我想和PK比较两件事时,我只想比较它们的PK。所以,我试图定义如下:

代码语言:javascript
复制
{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE UndecidableInstances #-}

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

但现在它给了我:

代码语言:javascript
复制
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.

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-13 09:30:21

这里需要一个函数依赖关系:

代码语言:javascript
复制
class Eq b => HasPK a b | a -> b where
  getPK :: a -> b

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

问题在于同一类型有多个PKs的可能性,如

代码语言:javascript
复制
instance HasPK MyType Int where ...
instance HasPK MyType String where ...

由于后面可以添加上面的双重实例,所以像(==) `on` getPK这样的代码可能是不明确的。实际上,当添加上面的实例时,它没有指定是使用Int PK还是使用String PK。

然而,像这样的实例

代码语言:javascript
复制
instance (HasPK a b) => Eq a where
  ...

可能会导致问题,因为它与任何其他Eq实例重叠。这里小心点。我会写

代码语言:javascript
复制
equalPK :: HasPK a b => a -> a -> Bool
equalPK = (==) `on` getPK

然后向所有相关类型提供显式实例,如下所示:

代码语言:javascript
复制
instance Eq MyType1 where (==) = equalPK
instance Eq MyType2 where (==) = equalPK
...

作为另一种选择,您可以使用一个类型家族,如

代码语言:javascript
复制
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
...
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29028714

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档