Haskell初学者:“没有......因...而产生的错误”错误
我的目标是编写一个函数来计算低于特定数字'n'的最大Collatz数。 (对于那些熟悉的人来说,这是个项目欧拉问题。)Haskell初学者:“没有......因...而产生的错误”错误
某些上下文:给定整数的Collatz数等于该整数的Collatz序列的长度。一个整数的Collatz序列计算如下:序列中的第一个数字(“n0”)是该整数本身;如果n0是偶数,序列中的下一个数字(“n1”)等于n/2;如果n0是奇数,那么n1等于3 * n0 + 1。我们继续递归地扩展序列直到我们到达1,此时序列结束。例如,5的collatz序列是:{5,16,8,4,2,1}(因为16 = 3 * 5 + 1,8 = 16/2,4 = 8/2,...)
我想写一个函数(“maxCollatzUnder”),当它传递一个整数“m”时,返回具有最长Collatz序列(即最大Collatz数)的整数(小于或等于m) 。例如,maxCollatz 20(即,下面的哪个整数(包括)20具有最长的拼贴序列?)应该返回19(数字19具有长度为21的Collatz序列:[19,58,29,88,44,22, 11,34,17,52,26,13,40,20,10,5,16,8,4,2,1])。
在下面的代码中,“collatz”和“collatzHelper”函数编译并正确运行。我在使用“maxCollatzUnder”功能时遇到了问题。该函数旨在(1)为1到m范围内的每个整数x(其中m是函数参数)创建一个2元组(x,y)的列表,其中y表示整数x的Collatz数,然后II)浏览列表中为最高在Collatz数(即,y),并返回其相关的整数(即X)
maxCollatzUnder n = foldl(\acc (i,j) -> if j > acc then i else acc) 0
(zip [1..n] (map collatzLength [1..n]))
where collatzLength n = length . collatz $ n
collatz n = map truncate $ collatzHelper n
collatzHelper 0 = [0]
collatzHelper 1 = [1]
collatzHelper n
| (truncate n) `mod` 2 == 0 = [n] ++ collatzHelper (n/2)
| otherwise = [n] ++ collatzHelper (3*n+1)
我收到以下错误,当我(尝试)编制。
*Main> :l PE14Collatz.hs
[1 of 1] Compiling Main (PE14Collatz.hs, interpreted)
PE14Collatz.hs:7:89:
No instance for (RealFrac Int)
arising from a use of `collatzLength'
In the first argument of `map', namely `collatzLength'
In the second argument of `zip', namely
`(map collatzLength [1 .. n])'
In the third argument of `foldl', namely
`(zip [1 .. n] (map collatzLength [1 .. n]))'
Failed, modules loaded: none.
有什么奇怪的是,代码编译,如果我改变“maxCollatzUnder”下面的代码(见下文)运行正常。唯一的变化是,在下面的版本中,折叠函数返回“j”(即,最大Collatz数)而不是“i”(即,产生最大Collatz数的整数)。
maxCollatzUnder n = foldl(\acc (i,j) -> if j > acc then j else acc) 0
(zip [1..n] (map collatzLength [1..n]))
where collatzLength n = length . collatz $ n
对更高效/优雅的方法的建议是受欢迎的,尽管我仍然有兴趣了解这个错误的原因。
因为你使用的truncate
(的RealFrac
的方法)和/
(的Fractional
的方法中,RealFrac
超类)的,哈斯克尔推断出以下两种类型签名的最后两个功能:
collatz :: (RealFrac a, Integral b) => a -> [b]
collatzHelper :: RealFrac a => a -> [a]
哈斯克尔然后尝试推算的maxCollatzUnder
类型,其思维过程是这样的:
“在
collatzLength n = length . collatz $ n
,我们通过n
到collatz
,所以collatzLength
的参数必须是RealFrac
。““因此,在
map collatzLength [1..n]
,[1..n]
必须是RealFrac
值的列表。“”因此,在
map collatzLength [1..n]
的n
必须是RealFrac
类型。“”。因此,在
zip [1..n]
的n
(其是相同n
)必须是RealFrac
式等[1..n]
是一个的RealFrac
名单。”“因此,在
(\acc (i,j) -> if j > acc then i else acc)
的i
必须是RealFrac
。”“由于上述的λ可以返回
i
或acc
,它们必须是相同的类型”“因为
j
正在相比acc
,j
必须是相同的类型acc
- 并且因此相同类型i
和RealFrac
。“”但WAIT -
j
为collatzLength
的返回值,这是length
一个调用的返回值,因此它必须是一个Int
,但Int
不在RealFrac
!“”错误!错误!”
我现在得走了(编译惊天动地不喜欢我放弃自己的秘密),但最短的解决方法是不使用truncate
和/
,只是使用div
的(地板),整数
你认为这些函数的类型是什么?例如,“collatz”的类型应该是什么? – bheklilr 2014-10-02 02:16:52