代码之家  ›  专栏  ›  技术社区  ›  gihan

Haskell中Eq的子类中的默认定义[duplicate]

  •  3
  • gihan  · 技术社区  · 10 年前

    我有一个类似于 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’)
    

    我是想在哈斯克尔做些不可能的事吗?我知道我可以做一些类似的事情

    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 ,而不是将其作为默认定义。

    我也意识到如果我用自己的超类而不是 等式 ,我本可以写

    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
    

    我的问题是超类是 等式 ,并且我不想在每个实例中重复相同的定义。

    1 回复  |  直到 9 年前
        1
  •  1
  •   phadej    10 年前

    您可以使用相同的名称定义函数(和运算符),只要它们位于不同的模块中即可。 所以有 Prelude.== (默认一个)和您的(例如, 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
    

    然而,我更喜欢使用其他操作员名称,例如 ~= .

    推荐文章