基于约束的Haskell实例分派

时间:2019-02-24 23:36:38

标签: haskell

我试图弄清楚如何在class内定义将针对数据的特定约束而适当调用的函数。因为我是Haskell新手,所以我不确定前面的术语是否用正确的术语表达,但是下面的示例可能会更清楚,下面的示例与我到目前为止的内容非常接近:

{-# LANGUAGE ConstrainedClassMethods #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}

module Test where

class (Eq a) => AssertEqual a where
   assertEqual :: AssertEqual a => a -> a -> Bool


instance AssertEqual String where
    assertEqual a b
        |    a == b = True
        | otherwise = error $ "Oops. " ++ show a ++ " is not equal to " ++ show b


data Foo = Foo Int deriving Eq

instance AssertEqual Foo where
    assertEqual a b
      |    a == b = True
      | otherwise = error "The two Foos are not equal, but I can't show them to you."

instance (Eq a, Show a) => AssertEqual a where
    assertEqual a b
      |    a == b = True
      | otherwise = error $ "The two items are not equal. One is " ++ (show a) ++ " and the other is " ++ (show b)

以上编译(GHC 8.0.2),但是当我调用assertEqual "hi" "hi"时,出现错误,提示实例重叠。我了解为什么实例在这种情况下会重叠,并且我想我也了解为什么这是一件坏事,但是我不知道是否有解决方案。或者,当然,如果我想要的东西本身就是一个坏主意(如果是这样,那么为什么这是个坏主意。)

1 个答案:

答案 0 :(得分:1)

示例中实例重叠的问题可以通过为其中的最后一个实例添加OVERLAPPABLE指令来解决:

instance {-# OVERLAPPABLE #-} (Eq a, Show a) => AssertEqual a where
assertEqual a b
  |    a == b = True
  | otherwise = error $ "The two items are not equal. One is " ++ (show a) ++ " and the other is " ++ (show b)

但是,正如Alec所亲切提及的那样,允许约束约束指示函数分派的更普遍的问题目前没有很好的解决方案。