实例方程式在Haskell中不起作用

时间:2018-08-10 08:39:06

标签: haskell instance

所以给了我以下数据类型,我不得不编写代码来检查元素是否在列表中(我想我做到了这一点)。 之后,我必须声明实例Eq,如果我的两个金额列表都相等,则它将为True。我应该使用我先前编写的元素代码。 有人可以告诉我我在做什么错吗?

   data Amount a = Amount [a] 

element [] _ = False
element (x:xs) y = ( x==y) || element xs y

instance Eq (Amount a) where 
      Amount xs == Amount ys = element xs ys && element ys xs

这是我收到的错误消息

 • Couldn't match expected type ‘a’ with actual type ‘[a]’
      ‘a’ is a rigid type variable bound by
        the instance declaration at Probeklausur1.hs:43:10-22
    • In the second argument of ‘element’, namely ‘ys’
      In the first argument of ‘(&&)’, namely ‘element xs ys’
      In the expression: element xs ys && elementS ys xs
    • Relevant bindings include
        ys :: [a] (bound at Probeklausur1.hs:44:27)
        xs :: [a] (bound at Probeklausur1.hs:44:14)
        (==) :: Amount a -> Amount a -> Bool
          (bound at Probeklausur1.hs:44:17)
   |
44 |       Amount xs == Amount ys = element xs ys && elementS ys xs     |                                           ^^

Probeklausur1.hs:44:49: error:
    • Variable not in scope: elementS :: [a] -> [a] -> Bool
    • Perhaps you meant ‘element’ (line 40)
   |
44 |       Amount xs == Amount ys = element xs ys && elementS ys xs     |                                                 ^^^^^^^^

1 个答案:

答案 0 :(得分:4)

让我们首先分析element的类型:

element [] _ = False
element (x:xs) y = ( x==y) || element xs y

我们看到第一项是列表[a](基于[](:)数据构造函数)。此外,我们知道第二项具有列表元素类型的类型,因此a,并且由于我们调用x == y,因此必须存在Eq a约束。因此我们得出:

element :: Eq a => [a] -> a -> Bool

为此已经存在一个非常相似的内置函数:elem :: Eq a => a -> [a] -> Bool,因此最好使用此函数。

但是让我们现在来看一下实例声明:

instance Eq (Amount a) where 
    Amount xs == Amount ys = element xs ys && element ys xs

这里有两个问题:

  1. 我们还需要a具有Eq类型约束,因为我们需要检查列表中的 elements 是否相同;和
  2. 我们用elementxs来调用ys,但是xsys的类型都是[a],所以这是行不通的。

因此,我们首先需要一种机制来检查一个列表的 all 个元素是否出现在另一个列表中。我们可以使用all :: (a -> Bool) -> [a] -> Bool函数进行检查:

allElem :: Eq a => [a] -> [a] -> Bool
allElem xs = all (flip elem xs)

所以现在我们可以这样写:

instance Eq a => Eq (Amount a) where 
    Amount xs == Amount ys = allElem xs ys && allElem ys xs

请注意,由于以下两个原因,以上内容可能仍然不是您想要的:

    未选中两个列表的
  1. 顺序,我认为这是有意的;
  2. 如果一个元素在第一个列表中出现多次次,那么只要在第二个列表中至少出现一次,它不是不必重复那么多次一旦我们一切都好。因此,两个列表的长度可以不同,但​​仍然将两个Amount视为相等。