Haskell如何将两个同输入结构的函数合并为单函数双输出
原有代码问题
你贴出的function1和function2实际存在逻辑错误:无论if判断条件是否成立,函数都直接返回剩余列表的长度length xs,既没有递归遍历所有列表元素统计符合要求的条目数,也没有处理空列表的边界情况,实际运行无法得到正确的统计结果。
合并后的正确实现
我们可以让合并后的函数返回一个二元组,第一个元素为平均分≥4的记录总数,第二个元素为平均分<4的记录总数,实现如下:
递归实现(适合入门理解)
countScore :: [(String, Int, Int, Int)] -> (Int, Int) -- 空列表边界:两种统计数都为0 countScore [] = (0, 0) countScore ((_, note1, note2, note3):rest) = let -- 计算当前条目的平均分 avg = (note1 + note2 + note3) `div` 3 -- 递归得到剩余列表的统计结果 (passCount, failCount) = countScore rest in -- 根据当前条目平均分判断统计数加1的位置 if avg >= 4 then (passCount + 1, failCount) else (passCount, failCount + 1)
高阶函数简化实现
也可以用foldl高阶函数简化代码,不用手动写递归:
countScore :: [(String, Int, Int, Int)] -> (Int, Int) countScore = foldl step (0, 0) where step (pass, fail) (_, n1, n2, n3) = if (n1 + n2 + n3) `div` 3 >= 4 then (pass + 1, fail) else (pass, fail + 1)
使用示例
直接传入成绩列表即可同时得到两个统计结果:
-- 测试输入 scores = [("张三", 6, 4, 5), ("李四", 2, 3, 2), ("王五", 5, 5, 3)] -- 调用函数 main = print $ countScore scores -- 输出结果:(2,1) 即2条平均分≥4,1条平均分<4
内容的提问来源于stack exchange,提问作者Chelsea95
相关产品推荐
相关产品推荐

