haskell - Instance Eq 在 Haskell 中不起作用
问题描述
所以我得到了以下数据类型,我必须编写一个代码来检查一个元素是否在列表中(我认为我做对了)。在此之后,我必须声明实例 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
对于 this: 已经存在一个非常相似的内置函数elem :: Eq a => a -> [a] -> Bool
,因此最好改用这个。
但是现在让我们看一下实例声明:
instance Eq (Amount a) where
Amount xs == Amount ys = element xs ys && element ys xs
这里有两个问题:
- 我们还需要
a
有一个Eq
类型约束,因为我们需要检查列表的元素是否相同;和 - 我们
element
用xs
and调用ys
,但两者xs
都有ys
type[a]
,所以这不起作用。
因此,我们首先需要一种机制来检查一个列表的所有元素是否出现在另一个列表中。我们可以用这个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
请注意,上述内容可能仍然不是您想要的,原因有两个:
- 没有检查两个列表的顺序,我认为这是故意的;
- 如果一个元素在第一个列表中出现多次,那么它不必在第二个列表中出现那么多次,只要它至少出现一次就可以了。因此,两个列表的长度可以不同,但仍然认为两个
Amount
s 是相等的。
推荐阅读
- javascript - 使用formik时取消表单提交
- c# - 对列表右侧求和的错误结果
- python - 如何使用加入和正则表达式?
- django - Django通过不同的相关对象注释QuerySet中的几个相同的对象
- c - 如何在 C 程序中从 X11 获取更新的系统 DPI 信息?
- python - 使用 SVM 进行股票分析
- python - Python在具有条件的数据帧上汇总总和
- javascript - 如何自动刷新视图?
- python - Why Scrapy don't return a value from function?
- php - 我可以在 SQL 中使用 AND 运算符 2 次吗?