Haskell:如何以函数组合方式定义myButLast并添加额外行为?
解决Haskell
myButLast 参数不匹配报错+自定义错误提示的问题 嘿,我来帮你捋清楚这个问题!首先你遇到的「Equations for ‘myButLast'’ have different numbers of arguments」报错,大概率是因为你写函数定义时,某个子句的参数个数和其他子句不一致了。举个典型的错误例子:
myButLast [] = error "空列表没法取倒数第二个元素啊!" myButLast x:xs = myButLast xs -- 这里漏了括号!Haskell会把x和xs当成两个参数 myButLast [x,_] = x
上面第二行的x:xs没加括号,会被解析成myButLast x xs——也就是接受两个参数的函数,和其他只接受一个列表参数的子句冲突,自然就报错了。
回到你的核心问题:当然能用函数组合的方式定义myButLast,同时加上自定义错误处理! 下面给你两种可行的方案:
方案一:先修正参数问题,直接加自定义错误提示
先把基础的模式匹配写对,补全空列表和单元素列表的错误分支,保证所有子句都只接受一个列表参数:
myButLast :: [a] -> a myButLast [] = error "错误:空列表没有倒数第二个元素!" myButLast [_] = error "错误:单元素列表没有倒数第二个元素!" myButLast [x,_] = x myButLast (_:xs) = myButLast xs
这样不仅解决了参数不匹配的问题,空列表或单元素列表传入时,也会输出你想要的特定错误提示。
方案二:用函数组合结合Either(更安全的Haskell风格错误处理)
如果你不想用error直接终止程序(毕竟异常处理不够优雅),可以用Either String a类型返回错误信息或结果,同时用函数组合把逻辑拆解开:
首先写核心的取倒数第二个元素的函数(只处理合法的长列表):
myButLastCore :: [a] -> a myButLastCore [x,_] = x myButLastCore (_:xs) = myButLastCore xs
然后写一个列表合法性检查的函数,再用Kleisli组合子>=>把两个函数串起来:
eitherMyButLast :: [a] -> Either String a eitherMyButLast = checkListValid >=> (Right . myButLastCore) where checkListValid xs | null xs = Left "空列表无法取倒数第二个元素!" | length xs == 1 = Left "单元素列表无法取倒数第二个元素!" | otherwise = Right xs
这里的>=>就是函数组合的一种,专门用来组合返回Either(或其他Monad类型)的函数,先检查列表是否合法,再把合法的列表传给核心函数处理,完美实现了你的需求。
小总结
- 先搞定参数不匹配的问题:所有函数子句的参数个数必须一致,模式匹配时记得给
x:xs这种构造加括号! - 函数组合完全可以用来实现带自定义错误处理的
myButLast——要么用error补全模式匹配,要么用Maybe/Either结合组合子做更安全的错误处理。
内容的提问来源于stack exchange,提问作者Our
相关产品推荐
相关产品推荐

