首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell Collatz猜想

Haskell Collatz猜想
EN

Code Review用户
提问于 2014-05-27 17:00:58
回答 1查看 2.9K关注 0票数 6

为了开始在Haskell中进行适当的编程,我用Collatz的猜想编写了两个计算数字和序列的函数。我也对这个程序进行了大量的评论,因为它帮助我记住了一些事情。

代码语言:javascript
复制
-- 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

我做得如何?有什么大的错误,或小的事情我可以改进吗?

EN

回答 1

Code Review用户

回答已采纳

发布于 2014-05-27 20:15:51

在功能方面,您的代码没有什么问题,但是我们可以做一些事情来使它更加时尚和地道。

您忽略的第一件最重要的事情是始终为顶级定义提供类型签名。仅仅阅读函数的类型签名通常会让您对该函数将做什么(比如IO操作或高阶函数)有一种直觉,或者确认您所写的内容实际上做了一些您在调用编译器以检查您的工作之后所期望的事情。

代码语言:javascript
复制
collatz :: Int -> Int
cltzList :: Int -> [Int]

我们应该对您的定义做一些小的调整,使其与良好的Haskell风格保持一致,这不会影响功能,但会帮助您的函数定义更像英语定义,而不是计算机的说明。

当检查一个数字是否为偶数时,请使用函数even,而不是检查模块2中的值。even的定义可能是在隐藏项下执行相同的操作,但使用even表示的是您的意图,而不是方法。这样的更改将显著提高大型项目中代码的可读性。(此外,抽象出even允许该函数的实现者在不需要对代码进行任何更改的情况下更有效地更改定义,例如,even可能检查最不重要的位,而不是执行任何数学操作。)

代码语言:javascript
复制
collatz n | even n = n `div` 2

在调用error时,应该始终包含模块和函数名,以便代码的用户知道错误实际上起源于哪个函数。也就是说,如果有人用负数调用你的函数,他们会看到这样的error "Collatz.cltzList: The number must be positive"

代码语言:javascript
复制
*** Exception: Collatz.cltzList: The number must be positive

而不是这个

代码语言:javascript
复制
*** Exception: The number must be positive.

在这一行| n == 1 = [n]上,我会将[n]改为[1]。这是n唯一的价值,所以明示比聪明更好。

你有太多的评论没有什么价值。例如,您可以假设,除非您正在编写一本“Haskell入门”的书,否则您的读者将知道什么是模式保护,因此您不需要解释它们是什么或为什么使用它们。

最后,在下面的版本中,我已经清除了对空白的随意使用。这主要是一种美学效果,但我发现漂亮的代码比其他代码更容易阅读,这在Haskell代码中并不少见。

代码语言:javascript
复制
-- 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)
票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/51845

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档