我似乎陷入了一个问题,并且不知道如何处理它或我当前的代码做错了什么。
我必须编写一个名为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的新手,还在学习。我究竟做错了什么,我怎么能纠正它?
答案 0 :(得分:4)
首先,这看起来很奇怪。或许你做错了就是考虑这个问题......
但是如果你坚持下去,你想知道一个奇数位数的整数的属性......哦。还有很多可以改进的地方。对于初学者,(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"
| ...
然后,you can将数字“转换”为字符串。转换为字符串通常是一个非常令人讨厌的事情,因为它会抛出窗口中的所有结构,类型检查等;但是“位数”基本上是字符串的属性(十进制扩展),而不是数字本身,所以这对于这个特定任务来说并不完全不可见。这可行:
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
答案 1 :(得分:3)
您转换为数字列表,然后查找列表长度的一般方法没有任何问题。真正出错的地方是试图把所有东西塞进一个功能。正如您第一手发现的那样,它使调试变得非常困难。函数式编程最适合非常小函数。
如果您将整数转换为数字列表的责任分开,使用digs
函数(如this answer中的函数),则算法的其余部分将简化为:
oddDigits x | x <= 0 = error
oddDigits x = odd . length $ digs x
答案 2 :(得分:0)
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
。