函数`(y*y)<x'应用于两个参数,但其类型`Bool'没有

Dai*_*air 5 haskell

所以我正在研究问题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
Run Code Online (Sandbox Code Playgroud)

我的逻辑是创建一个isPrime函数,并在isPrime调用prime中存储一个函数来存储2个参数,我要检查的数字是否为prime(x)和迭代器来检查x的sqrt以下的所有数字并查看它们是否分开x.prime有3名警卫:

| ((y*y) < x) and ((x `mod` y) == 0) = prime x (y+1)
Run Code Online (Sandbox Code Playgroud)

这一行应该说:我传递的数字是否小于x(((y*y) < x))的平方根,如果检查是否x可被y(((xmod y) /= 0))整除,如果不是,我使用递归并递增y再次检查更高的数字.

这一行:

| ((y*y) >= x) = True
Run Code Online (Sandbox Code Playgroud)

应该是这样,如果平方根下面的所有数字都不分x,x必须是素数.

最后,这一行:

| otherwise = False
Run Code Online (Sandbox Code Playgroud)

意味着沿线的某个数字除以数字x,因此它不是素数.

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

((y*y) < x)
Run Code Online (Sandbox Code Playgroud)

GHCi说:

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

我认为<应该接受两个参数并返回一个Bool,错误信息对我来说没有意义.你能帮我搞清楚我做错了什么吗?谢谢.

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

| ((y*y) >= x) = True
Run Code Online (Sandbox Code Playgroud)

应该:

| ((y*y) > x) = True
Run Code Online (Sandbox Code Playgroud)

iva*_*anm 10

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

  • @anon:`和`被识别 - 它只是它不是一个中缀运算符.`和`是一个函数,它接受一个列表并返回该列表中的所有元素是否为"True".Haskell认为你试图做的是将函数`(y*y)<x`与`和`函数的参数一起应用.`(y*y)<x`不是函数,因此失败. (2认同)

por*_*ges 10

要解释这里发生的事情......问题不在于<,它与整个表达方式有关:

((y*y) < x) and ((x `mod` y) /= 0)
Run Code Online (Sandbox Code Playgroud)

你缺少的是反击and:

((y*y) < x) `and` ((x `mod` y) /= 0)
Run Code Online (Sandbox Code Playgroud)

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

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

and ((y*y) < x) ((x `mod` y) /= 0)
Run Code Online (Sandbox Code Playgroud)

现在来解释错误信息.编译器所说的是你试图将表达式((y*y) < x)用作函数.由于Haskell中的函数应用程序不使用括号,所以类似f x y的函数f应用于两个参数xy.

既然你忘了周围的反引号and,哈斯克尔解释((y*y) < x) and ((x `mod` y) /= 0)你尝试应用功能((y*y) < x)的参数and((x `mod` y) /= 0).当然,这不起作用,因为((y*y) < x)返回Bool,这不是一个函数,所以它抱怨"函数(y * y) < x应用于两个参数,但它的类型Bool没有".Bool不是函数类型,因此它没有参数.

...

当然,你现在遇到的另一个错误是它应该&&不是and- and有类型[Bool] -> Bool.

  • `&&`是"逻辑和"的函数,类型为`Bool - > Bool - > Bool`.`和`是类似`[Bool] - > Bool`的类似函数,因此在它周围放置反引号对此无济于事. (7认同)
  • 您可以使用带有两个反引号的反引号来包围一个字符串,以将其格式化为代码. (4认同)
  • Urgh.任何人都知道如何在反引号中加入反引号?我似乎无法摆脱它们. (2认同)