[英]Haskell Integer Odd Digits Checker
我似乎陷入了一个问题,不知道如何处理它或我当前的代码做错了什么。
我必须编写一个名为oddDigits的函数,它接受一个整数参数并返回一个布尔结果。 当且仅当参数是具有奇数位数的正整数时,它应该返回True。 如果参数为零或负数,则函数应该以错误消息停止。
此外,无法将参数转换为字符串。 必须使用递归。 我感觉每个数字可以递归地存储在列表中,然后列表的长度可以确定答案。
到目前为止,我有这个:
oddDigits :: Integer -> Bool
lst = []
oddDigits x
| (x < 0) || (x == 0) = error
| x `mod` 10 ++ lst ++ oddDigits(x `div` 10)
| length(lst) `mod` 2 /= 0 = True
| otherwise = False
对不起,如果代码看起来很糟糕。 我是Haskell的新手,还在学习。 我究竟做错了什么,我怎么能纠正它?
首先,这看起来很奇怪。 或许你做错了就是要考虑这个问题......
但是如果你坚持下去,你想知道一个奇数位数的整数的属性......哦。 有很多可以改进的地方。 首先, (x < 0) || (x == 0)
(x < 0) || (x == 0)
不需要括号 - <
和==
(中缀4)绑定比||
更紧密 。 如果您对此不确定,可以随时询问GHCi:
Prelude> :i ==
class Eq a where
(==) :: a -> a -> Bool
...
-- Defined in ‘GHC.Classes’
infix 4 ==
Prelude> :i ||
(||) :: Bool -> Bool -> Bool -- Defined in ‘GHC.Classes’
infixr 2 ||
但在这里你不需要||
无论如何,因为有一个小于或等于的专用运算符。 因此你可以写
oddDigits x
| x <= 0 = error "bla bla"
| ...
然后, 您可以将数字“转换”为字符串。 转换为字符串通常是一个非常令人讨厌的事情,因为它会抛出窗口中的所有结构,类型检查等; 但“数字位数”基本上是字符串的属性(十进制扩展),而不是数字本身,因此对于此特定任务而言,这并非完全不可见。 这可行:
oddDigits x
| x <= 0 = error "blearg"
| length (show x)`mod`2 /= 0 = True
| otherwise = False
然而,这是一个多余的冗余部门。 你正在检查某些东西是否为True
,然后给出True
作为结果......为什么不把它放在一个子句中:
oddDigits x
| x <= 0 = error "blearg"
| otherwise = length (show x)`mod`2 /= 0
这可能实际上是最好的实现。
对于任何正确 ,明智的任务,我不建议去字符串路线。 递归更好。 这是它的样子:
oddDigits 1 = True
oddDigits x
| x <= 0 = error "blearg"
| otherwise = not . oddDigits $ x`div`10
您转换为数字列表,然后查找列表长度的一般方法没有任何问题。 真正出错的地方是试图把所有东西塞进一个功能。 正如您第一手发现的那样,它使调试变得非常困难。 功能编程最适合非常小的功能。
如果你将整数转换为数字列表的责任分开,使用像这个答案的digs
函数,你的算法的其余部分简化为:
oddDigits x | x <= 0 = error
oddDigits x = odd . length $ digs x
leftaroundabout的最终答案是非常好的,但它对2,3和23这样的数字失败了。这是一个修复。
oddDigits x
| x <= 0 = error "blearg"
| x < 10 = True
| otherwise = not . oddDigits $ x`div`10
它比我最初的答案要优雅得多,如下。 我将它包括在内,介绍一个常见的功能范例,即问题的工人/包装转换。 这里的包装器提供了接口,并将工作传递给另一个函数。 请注意,否定性检查现在只需要进行一次。
oddDigits :: Integer -> Bool
oddDigits x
| x <= 0 = False
| otherwise = oddDigits' True x
oddDigits' :: Bool -> Integer -> Bool
oddDigits' t x
| x < 10 = t
| otherwise = oddDigits' (not t) $ x `div` 10
oddDigits'
带有一个内部数据,最初的Bool。 我的第一个想法是让Bool成为一个数字累加器,计算数字位数。 在这种情况下,需要提供“unwrapper”,在这种情况下是标准的“奇数”功能:
oddDigits x
| x <= 0 = False
| otherwise = odd . oddDigits'' 1 $ x
其中oddDigits'' :: Integer -> Integer -> Integer
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.