Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Debugging 帮助调试Haskell中的大数异常takeWhile行为_Debugging_Haskell_Integer - Fatal编程技术网

Debugging 帮助调试Haskell中的大数异常takeWhile行为

Debugging 帮助调试Haskell中的大数异常takeWhile行为,debugging,haskell,integer,Debugging,Haskell,Integer,首先,为这个模糊的标题道歉,但我不确定我到底在问什么(!) 在大学遇到Haskell之后,我最近开始愤怒地使用它,所以我把它当作一个扩展的Hello World来解决问题,真的。在我的一个答案中,我遇到了一个错误,它似乎表明我对语言的一个基本部分有误解,而这不是我从教程中可以解决的问题,也不是我知道的足以开始用谷歌搜索的问题 问题本身的简要描述-解决方案与素数有关,因此我想要一个无限素数列表,我实现了它(还没有优化!): 由于无限列表的计算可能有点繁琐,我当然会使用惰性计算来确保只计算我想要的位

首先,为这个模糊的标题道歉,但我不确定我到底在问什么(!)

在大学遇到Haskell之后,我最近开始愤怒地使用它,所以我把它当作一个扩展的Hello World来解决问题,真的。在我的一个答案中,我遇到了一个错误,它似乎表明我对语言的一个基本部分有误解,而这不是我从教程中可以解决的问题,也不是我知道的足以开始用谷歌搜索的问题

问题本身的简要描述-解决方案与素数有关,因此我想要一个无限素数列表,我实现了它(还没有优化!):

由于无限列表的计算可能有点繁琐,我当然会使用惰性计算来确保只计算我想要的位。例如,我可以向GHCI询问小于100的素数:

*Main> takeWhile (< 100) primes
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
*Main>takeWhile(<100)素数
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
现在有一部分我一点也不明白-当上限足够大时,我根本没有得到答案。特别是:

*Main> takeWhile (< 4000000000) primes
[]
*Main>takeWhile(<4000000000)素数
[]
这不是
takeWhile
本身的问题,也不是部分应用的函数的问题,因为
takeWhile(<4000000000)[2..]
正如我所期望的那样工作。我使用filter(在
primes
的定义中)没有问题,因为
takeWhile(<4000000000)(filter-偶[2..])
也会返回预期的结果

通过二进制搜索,我发现有效的最大上限是
2^31-1
,因此这显然意味着某种基于空间的约束(即最大的正符号整数)。然而:

  • 我的印象是Haskell对整数的大小没有语言限制,它们只受可用内存量的限制
  • 这个数字只出现在小于谓词中,我知道它至少在某些情况下可以像预期的那样工作。当然,当它应用于列表的元素时,它不应该关心它们来自哪里?仅看第一个元素,我知道当输入
    2
    来自
    filter偶数[2..]
    时,谓词返回true;我知道
    primes
    返回
    2
    作为其第一个元素。那么我的列表怎么可能是空的,这个谓词怎么会“对于2的某些值”失败呢

  • 如果有任何想法,我都会很感激,因为我没有足够的经验知道从哪里开始。感谢您花时间查看。

    haskell中有两种内置的整数类型:
    Int
    Integer
    <代码>整数是默认值,没有限制<代码>整数但是是有界的。由于您在
    isPrime
    4000000000的类型中显式使用
    Int
    ,因此isPrime4000000000被用作
    Int
    和溢出。如果您将
    isPrime
    的类型更改为
    Integer->Bool
    或更好的
    Integral a=>a->Bool
    (读:一个可以接受任何类型的
    Integral
    值并返回
    Bool
    的函数),它将按预期工作

    这里需要注意的重要一点(除了
    Int
    Integer
    之间的区别)是4000000000的类型取决于它的使用方式。如果它用作接受
    Int
    的函数的参数,则它将是
    Int
    (在32位系统上,它将溢出)。如果将其用作接受
    整数的函数的参数,则它将是
    整数(且永不溢出)。如果它被用作接受任何类型的
    积分的函数的参数,它也将是一个
    整数
    ,因为
    整数
    积分

    的默认实例,这是一个简单的答案(…我看到已经部分回答)-“过早的专门化”

    定义的第一部分“类型签名”指定:

    isPrime :: Int -> Bool
    
    Int
    不仅仅是表示
    Integer
    的“快捷方式”—它们是不同的类型!要成为挑剔的人(这反过来又会让其他人把我不准确的地方撕碎),这里有从不“不同的
    2
    ”值-它必须是Int类型,因为这就是您指定函数的方式(将2与函数的参数
    n
    进行比较,并且只允许比较相同类型的值,因此
    2
    被“固定”到
    Int
    类型

    哦,作为一个警告,Int类型是一种很有可能出现大小写的类型。如果您的系统是在64位环境中构建的,那么您的
    Int
    也将基于64位表示,并且您的示例将工作到2^63-1,而不是像您那样的2^31-1。请注意我的措辞:我有一台带有MS Windows的64位计算机操作系统,这意味着还没有正式的64位MinGW工具链-我的操作系统是64位的,但我的GHC版本是用32位库编译的,所以它有32位的
    Int
    s。当我使用Linux时,即使在虚拟机中,它也有64位的工具链,所以
    Int
    s是64位的。如果你使用了其中一个库,你可能没有注意到行为


    所以,我想这只是在对你的类型进行推理时要小心的另一个原因。(尤其是在Haskell,无论如何…)

    谢谢,我现在明白了。所以事实证明,它确实是
    2
    的不同值-
    Int
    vs
    Integer
    !这导致类型推断将字符串
    4000000000
    解释为两种情况下的不同数据类型,后者是
    Int
    ,因此有几百个负值百万,谢谢
    isPrime :: Int -> Bool