2012-03-16 15 views
5

Así que estoy trabajando en Problem 31.La función `(y * y) <x 'se aplica a dos argumentos, pero su tipo` Bool' no tiene ninguno

he escrito la siguiente función con la esperanza de determinar si un número es primo:

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 

Mi lógica era hacer una función isPrime, y tienen una función dentro de isPrime llamada prime para almacenar 2 parámetros, las número Quiero verificar si es primo (x) y un iterador para verificar todos los números debajo de sqrt de x y ver si dividen x. prime tiene 3 guardias:

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

Esta línea se supone que decir: es el número pasé menos de la raíz cuadrada de x (((y*y) < x)) y si se trata de comprobar si x es divisible por y (((x mod y) /= 0)) , si no es así, uso recursión e incremento y para volver a verificar con un número mayor.

Esta línea:

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

se supone que es como si todos los números por debajo de la raíz cuadrada no se dividen x de todos modos, x debe ser primordial.

Finalmente, esta línea:

| otherwise = False 

significa que un número en algún lugar a lo largo de la línea de un número x dividido por lo que no es primo.

Pensé que el código que escribí tenía sentido, sé que no es el más eficiente, teniendo en cuenta que podría verificar primos por debajo de sqrt x y no todos los números por debajo de sqrt x, pero de todos modos, tengo problemas con esto declaración:

((y*y) < x) 

GHCi dice:

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

pensé que el < se suponía que tomar en dos argumentos y devolver una Bool, el mensaje de error no tiene mucho sentido para mí. ¿Puedes ayudarme a descubrir qué estoy haciendo mal? Gracias.

Edición rápida ahora que lo tengo a correr, esta línea:

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

debería ser:

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

Respuesta

10

Para explicar lo que está sucediendo aquí ...el problema no es con <, es con toda la expresión:

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

lo que se pierde es los acentos abiertos alrededor and:

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

Cuando se utiliza una función infija así, si no es un operador (es decir, está hecho de símbolos, como ++), entonces debe rodearlo con palos de retroceso.

Alternativamente, se puede utilizar no como una función infija, como:

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

ahora para explicar el mensaje de error. Lo que el compilador está diciendo es que estás tratando de usar la expresión ((y*y) < x) como una función. Como la aplicación de función en Haskell no usa corchetes, cualquier cosa como f x y es una función f aplicada a dos argumentos x y y.

Desde que se olvidó de poner acentos abiertos en todo el and, Haskell interpreta ((y*y) < x) and ((x `mod` y) /= 0) a medida que se trata de aplicar la función ((y*y) < x) a los argumentos and y ((x `mod` y) /= 0). Por supuesto, esto no funciona, porque ((y*y) < x) devuelve Bool, que no es una función, por lo que se queja con "La función (y * y) < x se aplica a dos argumentos, pero su tipo Bool no tiene ninguno". Bool no es un tipo de función, por lo que no tiene argumentos.

...

Por supuesto, el otro error que tiene ahora es que debe ser && no and-and tiene tipo [Bool] -> Bool.

+2

Urgh. ¿Alguien sabe cómo incluir palos en el backticks en SO? Parece que no puedo escapar de ellos. – porges

+7

'&&' es la función para "lógico y", con tipo 'Bool -> Bool -> Bool'. 'y' es una función similar con el tipo' [Bool] -> Bool', por lo que colocar palos de atrás no ayudará aquí. – Ben

+0

@Porges: solucioné eso para ti. Por lo que sé, necesitas usar '...' con barras invertidas que se escapan hacia adentro. –

10

Creo que te refieres a utilizar en lugar de &&and. Después de hacer eso carga sin ningún error.

+0

Madre de Dios, se ejecuta ahora. Me he estado rascando por qué diablos no funciona, me sorprende que no me da algo como 'y' no se reconoce o algo así. Oh, nota lateral, cometí un pequeño error en mi algoritmo: '| ((y * y)> = x) = True' debe ser: '| ((y * y)> x) = True' – Dair

+1

@anon: 'and' también es una función, pero hace algo más. – porges

+2

@anon: 'y' es reconocido, es solo que no es un operador infijo. 'y' es una función que toma una lista y devuelve si todos los elementos en esa lista son' True'. Lo que Haskell pensó que intentabas hacer fue aplicar la función '(y * y) icktoofay

Cuestiones relacionadas