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

如何在Haskell中将[(Time, Person)]转换为含列表的[(Time, [Person])]元组列表

问题排查与修正

错误根源

  • 返回类型错误:你定义的函数返回值是[(Time, Person)],但预期输出的第二个字段是Person列表,对应返回类型应为[(Time, [Person])]。类型不匹配导致两个Person封装的字符串被直接拼接,出现Name1Name2的错误结果。
  • 模式匹配不全:你仅覆盖了空列表、列表长度≥2的场景,缺少列表仅含1个元素的处理分支,因此触发“缺少穷举模式”的报错。
  • :操作符使用错误::是元素拼接列表的操作符,签名为a -> [a] -> [a],你代码中y : b的右侧b是单个Person类型,不是列表,类型校验不通过导致代码无法运行。

修正代码

推荐使用span函数实现同时间分组,逻辑更简洁且无匹配遗漏:

groupTogether :: [(Time, Person)] -> [(Time, [Person])]
groupTogether [] = []
groupTogether ((currTime, currPerson) : rest) =
  -- 拆分出剩余列表中时间和当前时间相同、不同的两部分
  let (sameTimeItems, diffTimeItems) = span (\(t, _) -> t == currTime) rest
      -- 把当前Person和所有同时间的Person拼成列表
      groupPersons = currPerson : map snd sameTimeItems
  in (currTime, groupPersons) : groupTogether diffTimeItems

如果要保留你原来的双元素匹配写法,补全分支和类型即可:

groupTogether :: [(Time, Person)] -> [(Time, [Person])]
groupTogether [] = []
-- 补全单个元素分支,把Person包装为列表
groupTogether [(x, y)] = [(x, [y])]
groupTogether ((x, y) : (a, b) : ks)
  | x == a = groupTogether ((x, y) : ks) >>= \(t, ps) -> if t == x then [(t, b:ps)] else [(x,[y]),(a,[b])] ++ ks
  | otherwise = (x, [y]) : groupTogether ((a, b) : ks)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 15:45:03