为了开始在Haskell中进行适当的编程,我用Collatz的猜想编写了两个计算数字和序列的函数。我也对这个程序进行了大量的评论,因为它帮助我记住了一些事情。
-- The Collatz sequence takes in a number, and either
-- divides by 2 if it is even, or
-- multiplies it by 3 and adds 1 if it is odd.
-- The famous Collatz conjecture asks whether the sequence,
-- from any positive initial value, will reach 1.
-- a guard expression is used for the 'collatz' variable,
-- used for finding the next number in a sequence. This is
-- neater than if / else if.
collatz n
| n `mod` 2 == 0 = n `div` 2 -- if n is even, return n / 2
| otherwise = 3 * n + 1 -- else return 3n + 1
-- another guard expression, this time for the variable that
-- generates whole sequences. it is recursive, and takes
-- advantage of the 'collatz' variable too.
cltzList n
| n <= 0 = error "The number must be positive."
| n == 1 = [n] -- if n is 1 return n:[]
| otherwise = n:cltzList (collatz n) -- else, recursive-call我做得如何?有什么大的错误,或小的事情我可以改进吗?
发布于 2014-05-27 20:15:51
在功能方面,您的代码没有什么问题,但是我们可以做一些事情来使它更加时尚和地道。
您忽略的第一件最重要的事情是始终为顶级定义提供类型签名。仅仅阅读函数的类型签名通常会让您对该函数将做什么(比如IO操作或高阶函数)有一种直觉,或者确认您所写的内容实际上做了一些您在调用编译器以检查您的工作之后所期望的事情。
collatz :: Int -> Int
cltzList :: Int -> [Int]我们应该对您的定义做一些小的调整,使其与良好的Haskell风格保持一致,这不会影响功能,但会帮助您的函数定义更像英语定义,而不是计算机的说明。
当检查一个数字是否为偶数时,请使用函数even,而不是检查模块2中的值。even的定义可能是在隐藏项下执行相同的操作,但使用even表示的是您的意图,而不是方法。这样的更改将显著提高大型项目中代码的可读性。(此外,抽象出even允许该函数的实现者在不需要对代码进行任何更改的情况下更有效地更改定义,例如,even可能检查最不重要的位,而不是执行任何数学操作。)
collatz n | even n = n `div` 2在调用error时,应该始终包含模块和函数名,以便代码的用户知道错误实际上起源于哪个函数。也就是说,如果有人用负数调用你的函数,他们会看到这样的error "Collatz.cltzList: The number must be positive"
*** Exception: Collatz.cltzList: The number must be positive而不是这个
*** Exception: The number must be positive.在这一行| n == 1 = [n]上,我会将[n]改为[1]。这是n唯一的价值,所以明示比聪明更好。
你有太多的评论没有什么价值。例如,您可以假设,除非您正在编写一本“Haskell入门”的书,否则您的读者将知道什么是模式保护,因此您不需要解释它们是什么或为什么使用它们。
最后,在下面的版本中,我已经清除了对空白的随意使用。这主要是一种美学效果,但我发现漂亮的代码比其他代码更容易阅读,这在Haskell代码中并不少见。
-- Implements the Collatz sequence.
--
-- n / 2 if n is even
-- c(n) =
-- 3 * n + 1 if n is odd
module Collatz where
collatz :: Int -> Int
collatz n | even n = n `div` 2
| otherwise = 3 * n + 1
-- Produces the Collatz sequence for a given non-zero natural number
collatzList :: Int -> [Int]
collatzList n | n <= 0 = error "Collatz.collatzList: n must be positive"
| n == 1 = 1 : []
| otherwise = n : collatzList (collatz n)https://codereview.stackexchange.com/questions/51845
复制相似问题