Haskell中组合不同实现的函数避免类型错误及解决缩进错误问题
解决你的Haskell函数组合与缩进问题
首先,我帮你梳理下代码里的两个核心问题:缩进错误和函数调用/组合的语法问题,同时也会教你更优雅的函数组合方式,避免类型错误。
1. 修复缩进错误
Haskell对缩进的要求非常严格,where块里的所有定义必须保持相同的缩进级别。你的sortListForPriority和orderListByOrder函数中,focus函数的缩进需要和同块的smaller、larger对齐,否则编译器会直接报错。
2. 修复printUpdatedList的语法错误
你最后一个函数里漏掉了对generItemPosition的参数传递——generItemPosition需要接收输入列表xs,但你写的sortListForPriority(generItemPosition)没有传入参数,这会导致类型不匹配。
3. 更优雅的函数组合方式
Haskell的函数组合运算符(.)可以帮你避免嵌套括号,让代码更简洁易读。比如f (g (h x))可以写成(f . g . h) x,两者完全等价,而且类型检查会自动帮你验证是否匹配。
修复后的完整代码
-- 给每个元素添加初始位置索引 generItemPosition :: [([Char], Int)] -> [([Char], Int, Int)] generItemPosition = zipWith (\ z (x, y) -> (x, y, z)) [1 ..] -- 按优先级(第二个元素)排序 sortListForPriority :: [([Char], Int, Int)] -> [([Char], Int, Int)] sortListForPriority [] = [] sortListForPriority (x: xs) = sortListForPriority smaller ++ [x] ++ sortListForPriority larger where smaller = filter (\ y -> focus y <= focus x) xs larger = filter (\ y -> focus y > focus x) xs focus (_, priority, _) = priority -- 和smaller、larger保持相同缩进 -- 更新优先级为排序后的位置(重新分配1、2、3...) updatePriority :: [([Char], Int, Int)] -> [([Char], Int, Int)] updatePriority = zipWith (\ newPriority (x, _, pos) -> (x, newPriority, pos)) [1 ..] -- 按初始位置(第三个元素)排序 orderListByOrder :: [([Char], Int, Int)] -> [([Char], Int, Int)] orderListByOrder [] = [] orderListByOrder (x: xs) = orderListByOrder smaller ++ [x] ++ orderListByOrder larger where smaller = filter (\ y -> focus y <= focus x) xs larger = filter (\ y -> focus y > focus x) xs focus (_, _, originalPos) = originalPos -- 同样保持缩进对齐 -- 组合所有步骤并返回结果 printUpdatedList :: [([Char], Int)] -> [([Char], Int, Int)] printUpdatedList = orderListByOrder . updatePriority . sortListForPriority . generItemPosition -- 等价于原始写法:printUpdatedList xs = orderListByOrder (updatePriority (sortListForPriority (generItemPosition xs)))
关于类型匹配的说明
你担心的类型错误问题,只要确保每个函数的输出类型和下一个函数的输入类型一致就不会出错:
generItemPosition的输出是[([Char], Int, Int)],正好是sortListForPriority的输入类型sortListForPriority的输出和updatePriority的输入完全匹配updatePriority的输出又和orderListByOrder的输入一致- 最后
orderListByOrder的输出就是printUpdatedList的返回类型,整个链路的类型完全兼容
内容的提问来源于stack exchange,提问作者Igor Gewehr
相关产品推荐
相关产品推荐

