【问题标题】:The function `(y * y) < x' is applied to two arguments, but its type `Bool' has none函数 `(y * y) < x' 应用于两个参数,但它的类型 `Bool' 没有
【发布时间】:2012-04-01 15:39:17
【问题描述】:

所以我正在处理Problem 31

我编写了以下函数,希望确定一个数字是否为素数:

isPrime :: Integer -> Bool

isPrime x = prime x 2
            where
            prime :: Integer -> Integer -> Bool
            prime x y | ((y*y) < x) and ((x `mod` y) /= 0) = prime x (y+1)
                      | ((y*y) >= x) = True
                      | otherwise = False

我的逻辑是创建一个 isPrime 函数,并在 isPrime 中有一个名为 prime 的函数来存储 2 个参数,我想检查它是否为素数 (x) 和一个迭代器检查 x 的 sqrt 下面的所有数字,看看它们是否除以xprime有3个守卫:

| ((y*y) < x) and ((x `mod` y) == 0) = prime x (y+1)

这条线应该说:是我传递的数字小于 x 的平方根(((y*y) &lt; x)),如果它是检查x 是否可以被y 整除(((xmody) /= 0) ),如果不是,我使用递归并增加 y 以再次检查更大的数字。

这一行:

| ((y*y) >= x) = True

应该是这样的,如果平方根以下的所有数字无论如何都不除 x,x 必须是素数。

最后,这一行:

| otherwise = False

表示沿线某处的数除以 x,因此它不是素数。

我认为我写的代码是有道理的,我知道它不是最有效的,考虑到我可以只检查 sqrt x 以下的素数而不是 sqrt x 以下的所有数字,但无论如何,我对这个语句有疑问:

((y*y) < x)

GHCi 说:

The function `(y * y) < x' is applied to two arguments, but its type `Bool' has none

我认为&lt; 应该接受两个参数并返回一个 Bool,错误消息对我来说并没有什么意义。你能帮我弄清楚我做错了什么吗?谢谢。

现在我可以运行它,快速编辑,这一行:

| ((y*y) >= x) = True

应该是:

| ((y*y) > x) = True

【问题讨论】:

    标签: haskell


    【解决方案1】:

    解释一下这里发生了什么...问题不在于&lt;,而在于整个表达式:

    ((y*y) < x) and ((x `mod` y) /= 0)
    

    你缺少的是 and 周围的反引号:

    ((y*y) < x) `and` ((x `mod` y) /= 0)
    

    当你使用这样的函数中缀时,如果它不是运算符(即由符号组成,如++),那么你需要用反引号括起来。

    或者,您可以将其用作非中缀的函数,例如:

    and ((y*y) < x) ((x `mod` y) /= 0)
    

    现在解释错误信息。编译器的意思是您正在尝试将表达式 ((y*y) &lt; x) 用作函数。由于 Haskell 中的函数应用程序不使用方括号,因此 f x y 之类的函数 f 应用于两个参数 xy

    由于您忘记在and 周围加上反引号,当您尝试将函数((y*y) &lt; x) 应用于参数and((x `mod` y) /= 0) 时,Haskell 会解释((y*y) &lt; x) and ((x `mod` y) /= 0)。当然,这不起作用,因为((y*y) &lt; x)返回Bool,这不是一个函数,所以它抱怨“函数(y * y) &lt; x应用于两个参数,但它的类型Bool没有” . Bool 不是函数类型,因此它没有参数。

    ...

    当然,您现在遇到的另一个错误是它应该是 &amp;&amp; 而不是 and - and 的类型为 [Bool] -&gt; Bool

    【讨论】:

    • 呃。任何人都知道如何在 SO 的反引号中包含反引号?我似乎无法逃脱他们。
    • &amp;&amp; 是“逻辑与”的函数,类型为Bool -&gt; Bool -&gt; Booland 是一个与 [Bool] -&gt; Bool 类型类似的函数,所以在它周围加上反引号将无济于事。
    • @Porges:为你解决了这个问题。据我所知,您需要使用 &lt;code&gt;...&lt;/code&gt; 内部带有反斜杠转义的反引号。
    • 你可以只用两个反引号包围一个字符串,将其格式化为代码。
    • @Ben:你读过整本书吗?这就是最后一点所说的。
    【解决方案2】:

    我认为您的意思是使用&amp;&amp; 而不是and。完成后,它加载没有任何错误。

    【讨论】:

    • 它现在运行的上帝之母。我一直在摸索为什么它不起作用,我很惊讶它没有给我像 and 不被识别或类似的东西。哦,旁注我在算法中犯了一个小错误:| ((y*y) &gt;= x) = True 应该是:| ((y*y) &gt; x) = True
    • @anon: and 也是一个函数,但它做了别的事情。
    • @anon: and 被识别——只是它不是中缀运算符。 and 是一个函数,它接受一个列表并返回该列表中的所有元素是否都是True。 Haskell 认为您尝试做的是将函数 (y * y) &lt; xand 函数的参数一起应用。 (y * y) &lt; x 不是函数,所以它失败了。
    • @anon and 被识别;这是一个类型为[Bool] -&gt; Bool 的函数。可以有一个类型为([Bool] -&gt; Bool) -&gt; Bool -&gt; Bool 的函数,这是(y * y) &lt; x 表达式位置所需的类型。因此,关于使用 Bool 类型表达式的消息确实是编译器在这里可以给你的最准确的错误;这是唯一的问题。
    猜你喜欢
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 2010-11-24
    相关资源
    最近更新 更多