类型构造函数或类错误

时间:2010-10-30 20:13:40

标签: haskell

dreiNplusEins :: Integer -> [Integer]
dreiNplusEins n = if n == 1 then [1] else if n `mod` 2 == 0 then
                        [n] ++ dreiNplusEins (n `div` 2)
                                        else
                        [n] ++ dreiNplusEins (n * 3 + 1)

maxZyklus :: UntereGrenze -> ObereGrenze -> (UntereGrenze,ObereGrenze,MaxZyklaenge)
maxZyklus m n = if m > n then (m,n,0) else if m == n then 
                         (m,n,length(dreiNplusEins m))
                         else 
                         (m,n,0)
type UntereGrenze = Integer
type ObereGrenze  = Integer
type MaxZykLaenge = Integer

这是我的程序,这给出了错误,因为不在范围内:类型构造函数或类`MaxZyklaenge'我该如何修复它?

4 个答案:

答案 0 :(得分:6)

类型名称中有拼写错误:

maxZyklus的类型签名中,您编写MaxZyklaenge(小写l),但在类型定义中,您编写MayZykLaenge(大写L)。

答案 1 :(得分:4)

即使你修正了拼写错误,你仍然会收到错误,因为length会返回Int,而你需要Integer。以下是解决此问题的一种方法(我还重写了使用警卫的代码):

import Data.List (genericLength)

dreiNplusEins :: Integer -> [Integer]
dreiNplusEins 1 = [1]
dreiNplusEins n
  | n `mod` 2 == 0 = n : dreiNplusEins (n `div` 2)
  | otherwise      = n : dreiNplusEins (n * 3 + 1)

maxZyklus :: UntereGrenze -> ObereGrenze -> (UntereGrenze, ObereGrenze, MaxZyklaenge)
maxZyklus m n
 | m == n    = (m, n, genericLength $ dreiNplusEins m)
 | otherwise = (m, n, 0)

type UntereGrenze = Integer
type ObereGrenze  = Integer
type MaxZyklaenge = Integer

如果您不想要额外的fromIntegral . length,也可以使用import,但我个人认为genericLength更清晰一点。


另外,如果你感兴趣的话,这是编写第一个函数的一种可以说是更好的方法:

dreiNplusEins :: Integer -> [Integer]
dreiNplusEins = (++[1]) . takeWhile (/=1) . iterate f
  where
    f n | even n    = n `div` 2
        | otherwise = n * 3 + 1

这只是说“迭代地应用f直到你点击1,然后在最后点1。”


要查找产生最长链的给定范围内的数字,可以使用以下函数:

longestBetween :: (Enum a, Integral b) => (a -> [b]) -> (a, a) -> (a, b)
longestBetween f (m, n)
  = maximumBy (comparing snd)
  . zip [m..n] $ map (genericLength . f) [m..n]

第一个参数是创建列表的函数,第二个参数是范围。返回值是一个元组,包含范围中的所需数字和列表的长度。请注意,我们需要这些额外的导入:

import Data.List (genericLength, maximumBy)
import Data.Ord (comparing)

我们可以测试如下:

*Main> longestBetween dreiNplusEins (100, 1000) 
(871,179)

实现您在评论中指定的maxZyklus函数只需要进行一些小的更改:

maxZyklus m n = (m, n, maximum $ map (genericLength . dreiNplusEins) [m..n])

maxZyklus 11 22提供了所需的(11, 22, 21)

答案 2 :(得分:1)

Haskell区分大小写。

maxZyklus的类型签名中:

 ... ,MaxZyklaenge)
-- #        ^

但你有:

 type MaxZykLaenge = Integer
-- #        ^

答案 3 :(得分:0)

它被定义为MaxZykLaenge(注意“L”),而你将类型写为“MaxZyklaenge”。 Haskell区分大小写。