首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Collatz函数的实现

Collatz函数的实现
EN

Stack Overflow用户
提问于 2014-04-14 01:51:57
回答 2查看 289关注 0票数 0

给你一个哈斯克尔提到了Collatz序列:

我们取一个自然数。如果这个数字是偶数,我们除以2。如果它是奇数,我们把它乘以3,然后再加1。

当我试图实现它时,我遇到了一个问题。

代码语言:javascript
复制
collatz :: (Integral a) => a -> [a]
collatz x 
 | odd x    = f x : collatz (f x)
 | otherwise = g x : collatz (g x)
     where f y = y*3 + 1
           g y = y/2   

但是我得到了编译时错误:

代码语言:javascript
复制
CollatzSeq.hs:10:16:
Could not deduce (Fractional a) arising from a use of `g'
from the context (Integral a)
  bound by the type signature for collatz :: Integral a => a -> [a]
  at CollatzSeq.hs:7:12-35
Possible fix:
  add (Fractional a) to the context of
    the type signature for collatz :: Integral a => a -> [a]
In the first argument of `(:)', namely `g x'
In the expression: g x : collatz (g x)
In an equation for `collatz':
    collatz x
      | odd' x = f x : collatz (f x)
      | otherwise = g x : collatz (g x)
      where
          f y = y * 3 + 1
          g y = y / 2

据我所知,问题是调用collatz (g x)可以返回Fractional,因为y / 2返回Double

代码语言:javascript
复制
Prelude> let x = 4 / 2
Prelude> :t x
x :: Double

我试图通过在floor前面添加y/2来修复这个类型错误,但这是行不通的。

请告诉我如何纠正这个错误。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-14 01:57:50

使用div而不是(/)。或者,如果您想要另一种舍入策略而不是floor,您可以使用fromIntegral,如

代码语言:javascript
复制
round (fromIntegral y / 2)
票数 5
EN

Stack Overflow用户

发布于 2014-04-14 02:13:56

错误来自定义/的方式。GHCI显示了:t (/)的这个结果。

代码语言:javascript
复制
(/) :: Fractional a => a -> a -> a

另一种选择是使用div,它具有类型签名:

代码语言:javascript
复制
div :: Integral a => a -> a -> a

其次,您正在跳过当前实现中的输入项。情况不应如此。

最后,您需要添加输入= 1的大小写,否则函数将陷入无限循环。您可以将其更改为:

代码语言:javascript
复制
collatz :: (Integral a) => a -> [a]
collatz 1 = [1]
collatz x 
 | odd x    = x : collatz (f x)
 | otherwise = x : collatz (g x)
 where f y = y*3 + 1
       g y = y `div` 2
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23050749

复制
相关文章

相似问题

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