我试图编写一个返回重复元素的函数
findMul :: [String] -> String
findMul [] = []
findMul s
|ss!!0 == ss!!1 = ss!!0
|otherwise = findMul (tail s)
where
ss = sort s
sort :: [String] -> [String]
sort [] = []
sort (x:ys) = (sort ls) ++ [x] ++ (sort gs)
where
ls = [y | y<-ys, y<=x]
gs = [y | y<-ys, y>x ]
使用输入
进行测试时,这似乎有效findMul ["d","c","b","a","a"]
正确返回
"a"
但是当我用稍微不同的输入进行测试时
findMul ["d","c","b","b","a"]
返回错误
*** Exception: Prelude.(!!): index too large
任何人都可以解释错误的含义吗?可能为什么会这样?
答案 0 :(得分:2)
您的sort
功能没问题;问题在于findMul
函数的定义。注意第二种模式,
findMul s
如果列表s
非空,则使用。特别是,在s
的情况下使用的是单例列表(仅由一个元素组成的列表)。
此外,列表s
和ss
的长度始终相同;因此,如果s
只有一个元素,ss
也只有一个元素。
但是,在ss!!1
中,您尝试访问ss
的第二个元素,不如果s
是单例列表,则存在。您实际上是在尝试访问超出列表ss
的实际长度(即1)的元素!这就是Haskell对你大吼大叫的原因:
*** Exception: Prelude.(!!): index too large
答案 1 :(得分:1)
findMul
的模式匹配可以采用单个元素列表
findMul ["b"]
发生这种情况时,ss
列表的长度也为1,但您在守护ss!!1
中使用其中的第二个元素。
这是错误。
答案 2 :(得分:1)
使用!
进行列表访问通常不是最好的主意。使用模式匹配,事情变得更加清晰。
findMul (x:y:rest) = if x == y then y else findMul (y:rest)
findMul [x] = x -- the branch you originally missed
findMul [] = undefined -- or what you'd prefer
很明显,您只能找到第一次重复。考虑完整的RLE:)