因此,我正在尝试实现一个函数,给定3个元素((Int,Int),Int)
的列表,当第二个位置上所有3个元素和True
的值相同时,返回False
否则。
例如,[((1,2),7),((5,3),7),((1,9),7)]
应该返回True
,而[((1,2),3),((5,3),3),((1,9),5)]
应该返回False
。
这是我的代码:
bc :: [((Int,Int),Int)]
wcheck :: [((Int,Int),Int)] -> Bool
wcheck bc
| (( fst(fst bc) == fst(snd bc) ) && ( fst(snd bc) == fst(last bc) )) = True
| otherwise = False
还有我得到的错误:
E:\\study related\Module1\week 4\ttt.hs:55:65: error:
* Couldn't match expected type `[(a, b0)]'
with actual type `((a, b), (a, b1))'
* In the first argument of `last', namely `bc'
In the first argument of `fst', namely `(last bc)'
In the second argument of `(==)', namely `fst (last bc)'
* Relevant bindings include
bc :: ((a, b), (a, b1))
(bound at E:\\study related\Module1\week 4\ttt.hs:54:8)
wcheck :: ((a, b), (a, b1)) -> Bool
(bound at E:\\study related\Module1\week 4\ttt.hs:54:1)
|
55 | | (( fst(fst bc) == fst(snd bc) ) && ( fst(snd bc) == fst(last bc) )) = True
|
能否请您告诉我为什么会出现此错误以及解决此错误的方法?谢谢。
答案 0 :(得分:2)
如果我们执行简单的模式匹配而不是使用fst :: (a, b) -> a
等,则可能会更容易。
我们可以使用模式((_, x), _)
从包裹在2元组中的2元组中获取第二个元素。
因此,我们可以使用模式匹配,例如:
wcheck :: [((Int,Int),Int)] -> Bool
wcheck [((_, x), _), ((_, y), _), ((_, z), _)] = x == y && y == z
wcheck _ = False
因此,如果列表中包含三个元素,则我们将这些元素解包,然后检查“第二个项目”是否彼此相等。如果模式不匹配(对于元素太少或太多的列表),我们只返回False
。
但是“三个元素的列表”没有多大意义。如果在编译时知道元素的数量,则最好使用元组,因为这样,编译器可以验证您只能为该函数提供3元组。
如果我们对元组的 second 项感兴趣,可以使用(_, x)
作为模式(我们对第一项都不感兴趣):
wcheck :: [((Int,Int),Int)] -> Bool
wcheck [(_, x), (_, y), (_, z)] = x == y && y == z
wcheck _ = False
请注意,我们可以使用以下方式概括签名:
wcheck :: Eq c => [((a, b), c)] -> Bool
wcheck [(_, x), (_, y), (_, z)] = x == y && y == z
wcheck _ = False
答案 1 :(得分:2)
fst
和snd
在这种情况下不是很好。我们可以通过进行模式匹配来提取我们关心的部分:
let (_,y) = x in ...
现在您要对列表中的每个元素执行此操作(以检查每个元素具有相同的第二个值):
map (\(_,x) -> x)
然后您要检查它们是否相等:
allEqual :: Eq a => [a] -> Bool
allEqual [] = True
allEqual (x:xs) = all (\y->x==y) xs
这将从列表(如果存在)中获取第一个元素x
,并检查是否其他项目y
满足x==y
现在我们可以编写您的函数了:
wcheck xs = allEqual (map (\(_,y) -> y) xs)
答案 2 :(得分:0)
鉴于您要测试外部对中第二个元素的相等性,有很多方法可以做到这一点,包括以下内容。
首先,映射snd
可为您提供以下元素:
λ> fmap snd [((1,2),7),((5,3),7),((1,9),7)]
[7,7,7]
现在您可以将它们分组为连续相等的数字的列表:
λ> import Data.List
λ> (group . fmap snd) [((1,2),7),((5,3),7),((1,9),7)]
[[7,7,7]]
如果此列表列表的长度最多为1(假设将这样的对的空列表定义为具有相等的第二个元素),则这些值相等:
λ> (length . group . fmap snd) [((1,2),7),((5,3),7),((1,9),7)]
1
将它们放在一起我们可以定义
import Data.List
equalSnds :: Eq a => [(b, a)] -> Bool
equalSnds xs = (length . group . fmap snd) xs <= 1
如此
λ> equalSnds [((1,2),7),((5,3),7),((1,9),7)]
True
λ> equalSnds [((1,2),3),((5,3),3),((1,9),5)]
False
如果您还想测试列表的长度,则可以单独进行操作:
wcheck :: [((Int,Int),Int)] -> Bool
wcheck xs = length xs == 3 && equalSnds xs