所以我得到了以下数据类型,我必须编写一个代码来检查元素是否在列表中(我认为我做对了(。 在此之后,我必须声明实例 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 | ^^^^^^^^
我们先分析一下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
这里有两个问题:
- 我们也需要
a
有一个Eq
类型约束,因为我们需要检查列表的元素是否相同; - 我们用
xs
和ys
来称呼element
,但xs
和ys
都有类型[a]
,所以这是行不通的。
因此,我们首先需要一种机制来检查一个列表的所有元素是否出现在另一个列表中。我们可以用all :: (a -> Bool) -> [a] -> Bool
函数来检查这一点:
allElem :: Eq a => [a] -> [a] -> Bool
allElem xs = all (flip elem xs)
所以现在我们可以这样写:
instanceEq a =>Eq (Amount a) where
Amount xs == Amount ys =allElem xs ys && allElem ys xs
请注意,由于两个原因,上述内容可能仍然不是您想要的:
- 两个列表的顺序没有检查,我认为这是故意的;
- 如果一个元素在第一个列表中多次出现,那么它不必在第二个列表中出现那么多次,只要它至少出现一次我们就好了。因此,两个列表的长度可以不同,并且两个
Amount
仍然被认为是相等的。