Haskell查找双字符子串索引时where定义变量报错问题求助
问题解答
首先明确:你的where语句语法使用完全正确,报错与where本身无关,问题出在表达式优先级解析和逻辑设计上。
报错原因
Haskell中函数调用的优先级高于列表构造运算符:,你写的locateZip x:xs会被编译器解析为(locateZip x) : xs,而非你预期的locateZip (x:xs)。
这就导致head接收的参数是一个嵌套列表,取出来的首元素仍然是列表类型,和你预期的((Char, Char), Int)类型不匹配,因此抛出了你遇到的类型错误。
其他需要修正的逻辑问题
- 索引计算错误:你每次递归传入切掉首字符的
xs,但locateZip生成的索引永远从0开始,就算后续匹配成功,返回的索引也是相对于子串的偏移,和主串的实际索引不符。 - 类型不匹配:判断条件中的
snd(fst h) == ys写法错误,ys是待匹配串的尾部(字符串类型),而snd(fst h)是Char类型,两者类型不同无法直接比较。 - 缺少边界处理:主串长度小于2时调用
tail会直接崩溃,没有匹配结果时会无限递归最终报错。
修正方案
如果你想保留原本的zip实现思路,可以改成如下写法:
locate :: String -> String -> Int locate mainStr pattern@[y1, y2] = case filter matchPair (locateZip mainStr) of [] -> error "未找到匹配子串" (_, idx):_ -> idx where locateZip xs = zip (zip xs (tail xs)) [0..] matchPair ((a, b), _) = a == y1 && b == y2 -- 处理待匹配串长度不为2的边界 locate _ _ = error "待匹配串长度必须为2"
运行验证
locate "aabba" "aa" -- 输出 0 locate "bbaab" "aa" -- 输出 2
内容的提问来源于stack exchange,提问作者Anders Stene
相关产品推荐
相关产品推荐

