Haskell中Eq的子类中的默认定义

时间:2015-12-24 22:44:30

标签: haskell subclass

我有一个类似于previous one的问题,但超类是Eq。例如,假设我有以下内容:

{-# LANGUAGE DefaultSignatures #-}
class (Eq a) => Foo a where
  size :: a -> Int
  (==) :: a -> a -> Bool
  (==) s t = (size s) == (size t)

(注意,我已经包含了上述问题解决方案中建议的语言扩展名)

我收到以下ghci错误消息:

Ambiguous occurrence ‘==’
It could refer to either ‘Main.==’,
                         defined at permutations.lhs:162:3
                      or ‘Prelude.==’,
                         imported from ‘Prelude’ at permutations.lhs:1:1
                         (and originally defined in ‘GHC.Classes’)

我是否想在Haskell做一些不可能的事情?我知道我可以做一些像

这样的事情
class (Eq a) => Foo a where
  size :: a -> Int

data Bar = Qux [Int]    

instance Foo Bar where
  size (Qux xs) = length xs

instance Eq Bar where
    (==) f g = (size f) == (size g)

但我必须为(==)的每个实例复制Foo的定义,而不是将其作为默认定义。

我也意识到,如果我使用自己的超类代替Eq,我本来可以写的

class Bam a where
  eqs :: a -> a -> Bool
  default eqs :: Roo a => a -> a -> Bool
  eqs f g = (size f) == (size g)

class (Bam a) => Roo a where
  size :: a -> Int

我遇到的问题是超类是Eq,而且我不想在每个实例中重复相同的定义。

1 个答案:

答案 0 :(得分:1)

您可以定义具有相同名称的函数(和运算符),只要它们位于不同的模块中即可。 所以有Prelude.==(默认值为1)和你的(例如My.==)。在My.==的默认定义中, 编译器不知道使用哪个。修复是微不足道的,但很难看:

{-# LANGUAGE DefaultSignatures #-}
module My where

class (Eq a) => Foo a where
  size :: a -> Int
  (==) :: a -> a -> Bool
  (==) s t = (size s) Prelude.== (size t)

instance Eq a => Foo [a] where
  size = length

main :: IO ()
main = do
    print $ a Prelude.== b
    print $ a My.== b
  where
    a = [1, 2, 3]
    b = [3, 4, 5]

运行时:

> main
False
True

然而,我更喜欢使用其他一些运营商名称,例如~=