Haskell中无法构造元组列表的问题求助
解决你的Haskell类型错误问题
首先,咱们先搞清楚GHC报错的根本原因——和你猜测的“把(x,y)识别为Int”完全没关系,是你对(==) on length这个组合的使用逻辑搞错了。
错误原因拆解
on函数的类型是(b -> b -> c) -> (a -> b) -> a -> a -> c,它的核心要求是:最后传入的两个参数必须是同类型的,因为它会对这两个参数都应用中间那个函数(这里是length),再用第一个函数(这里是==)比较结果。
你现在的代码里:
- 第一个参数是
nub $ map fst points,类型是[Int](提取所有点的x坐标后去重) - 第二个参数是
points,类型是[(Int, Int)](原始的点列表)
这两个参数类型完全不同,GHC自然会报错说无法把(Int, Int)匹配成Int——因为它期望第二个参数也是[Int]类型的列表。
修复方案
其实你的需求很明确:判断所有点的x坐标是否都是唯一的(去重后的x列表长度和原始点列表长度相等),完全不需要用on函数,直接写长度比较就清晰又正确:
check :: [(Int, Int)] -> Bool check points = length (nub $ map fst points) == length points
如果你非要用on函数(虽然没必要),那得让两个参数类型一致,比如把原始点列表也转换成x坐标列表,这样两个参数都是[Int]:
check points = ((==) `on` length) (nub $ map fst points) (map fst points)
不过这个逻辑就变成了“去重后的x列表长度等于原x列表长度”,和上面的效果是一样的,但多此一举,不如直接写更直观。
关于你尝试的无效操作
你提到“在read周围加类型声明、把return (x,y)换成return x”都没用,这是因为这些操作根本没触碰到问题的核心——on函数的参数类型不匹配问题。当你把return (x,y)换成return x时,points变成了[Int],这时候map fst points会因为fst需要元组参数而报错,和原来的错误不是同一个,只是你可能没注意到报错信息的变化。
内容的提问来源于stack exchange,提问作者yhylord
相关产品推荐
相关产品推荐

