Haskell二进制2^k位提取函数的参数校验与错误修正求助
修正Haskell函数
stelle的问题 我需要实现两项任务,其中第二项是用Haskell编写名为stelle的函数:
- 任务2:输入两个自然数n、k(非负整数),输出n的二进制表示中2^k位上的数字。
我两次尝试编写代码都存在问题,第一次代码最后一行有语法错误,原本想校验n和k必须为非负整数,不满足就抛出错误;第二次代码逻辑仍有问题,现寻求修正。
两次尝试的代码
第一次尝试
stelle :: Int -> Int -> Int stelle n 0 = mod n 2 stelle n k = stelle (div n 2) (k-1) stelle n k = n k <= O = error
第二次尝试
stelle :: Int -> Int -> Int stelle n 0 = mod n 2 stelle n k | n < 0 && k < 0 = error "Vorraussetzung nicht erfüllt" | n >= 0 && k >= 0 = (div n 2) (k-1)
问题分析
第一次尝试的问题:
- 最后一行完全不符合Haskell语法,既不是合法的模式匹配也不是守卫表达式,
O是拼写错误(应为数字0),整体写法导致语法报错。 - 参数校验逻辑的位置错误,Haskell模式匹配按顺序执行,错误分支写在最后无法被触发。
- 最后一行完全不符合Haskell语法,既不是合法的模式匹配也不是守卫表达式,
第二次尝试的问题:
- 守卫条件
n < 0 && k < 0仅校验两者同时为负的情况,但只要其中一个参数为负就属于非法输入,应使用逻辑或||而非逻辑与&&。 - 合法分支里的
(div n 2) (k-1)是错误写法:div n 2计算的是整数结果,不是函数,无法接收参数,正确做法是递归调用stelle函数。 - 缺少对部分非法情况的处理(比如n负k正、n正k负),会导致非穷尽模式匹配错误。
- 守卫条件
修正后的代码
stelle :: Int -> Int -> Int stelle n k | n < 0 || k < 0 = error "参数必须为非负整数" | k == 0 = mod n 2 | otherwise = stelle (div n 2) (k - 1)
修正说明
- 优先通过守卫表达式做参数校验,只要n或k为负就抛出错误,覆盖所有非法输入场景。
- 将k=0的终止条件放到守卫中,和递归分支清晰区分,避免模式匹配顺序问题。
- 递归分支正确调用
stelle函数,传递div n 2(二进制右移一位的结果)和k-1作为新参数,符合二进制位提取的逻辑。 - 用
otherwise覆盖所有合法的k>0情况,保证模式匹配穷尽,避免运行时错误。
内容的提问来源于stack exchange,提问作者user20676598
相关产品推荐
相关产品推荐

