You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell列表推导括号用法及crosswordFind函数实现问题

问题解答

1. 为什么你写的方括号不能用来分隔代码

Haskell 中的[]是列表专用语法,作用只有构造列表,不存在「分隔代码段」的语法作用。
你把判断表达式包在[]里,相当于把布尔类型的判断结果转换成了单元素布尔列表,而&&运算符只能作用于布尔值,不能作用于列表,这种写法本身就会触发类型错误。同时你初始版本外层的[]会把整个if表达式返回的[String]结果作为列表的唯一元素,得到的是[[String]]类型,和你声明的函数返回值[String]不匹配,这也是你提到返回长度为1的列表的原因。
如果需要调整运算优先级,Haskell 仅支持用小括号()包裹表达式,不要混淆其他语言的中括号用法。

2. 用列表推导实现crosswordFind函数

crosswordFind :: Char -> Int -> Int -> [String] -> [String]
crosswordFind letter pos len words = 
  [ word | word <- words, 
           length word == len,  -- 匹配单词长度要求
           pos >= 0, pos < length word,  -- 下标越界防护,避免运行时报错
           word !! pos == letter  -- 匹配指定位置的字符
  ]

你给出的测试用例crosswordFind 'k' 1 7 ["funky", "fabulous", "kite", "icky", "ukelele"]运行后会返回["ukelele"],符合预期。

3. 现有代码加粗部分的修正方案

你现有修改后的代码逻辑本身存在结构性问题:没有遍历words里的每个单词,直接对整个单词列表做判断,就算只替换加粗内容也无法正常运行,需要先调整整体逻辑,再修正你写反的条件参数。
你原代码的三个判断条件全部参数顺序错误,修正后的过滤逻辑如下:

crosswordFind :: Char -> Int -> Int -> [String] -> [String]
crosswordFind letter pos len words = 
  filter (\word -> length word == len && word !! pos == letter) words

如果非要保留你原来的if-else结构,需要把判断逻辑放到对每个单词的遍历中:

crosswordFind :: Char -> Int -> Int -> [String] -> [String]
crosswordFind letter pos len words = 
  concatMap (\word -> if length word == len && word !! pos == letter then [word] else []) words

你原来三处加粗内容对应的错误分别是:

  • 第一个words:不需要调用isAlpha做额外判断,且你应该取单个单词的指定位置字符,而非操作整个单词列表
  • 第二个words:你把下标和取值的参数写反了,正确逻辑是单词 !! 位置下标 == 目标字符,不是列表 !! 字符 == 位置下标
  • 第三个pos:对Int类型的pos求长度属于类型错误,正确逻辑是求单个单词的长度等于给定长度len

内容的提问来源于stack exchange,提问作者idontknowhowtocode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 01:18:02