2009-12-28 12 views
8

Estoy aprendiendo Haskell. He creado una función que devuelve la tabla de multiplicar hasta 'n' en la base 'b'. Los números se rellenan con dígitos 'w'. Como último paso, quiero calcular 'w' automáticamente. ¿Por qué esto no compila?No hay instancia para (Floating Int)

-- Number of digits needed for the multiplication table n*n in base 'base' 
nOfDg :: Int -> Int-> Int 
nOfDg n base = 1 + floor (logBase base (n*n)) 

error:

No instance for (Floating Int) 
    arising from a use of `logBase' at C:\haskel\dgnum.hs:4:24-38 
    Possible fix: add an instance declaration for (Floating Int) 
    In the first argument of `floor', namely `(logBase b (n * n))' 
    In the second argument of `(+)', namely `floor (logBase b (n * n))' 
    In the expression: 1 + floor (logBase b (n * n)) 

Respuesta

10

logBase toma dos parámetros que implementan la clase de tipos flotantes. Tendrá que llamar desde Integra en los parámetros antes de pasarlos a logBase. Este compilado para mí con 6.10.3:

nOfDg :: Int -> Int-> Int 
nOfDg n base = 1 + floor (logBase (fromIntegral base) (fromIntegral (n*n))) 

Hay que recordar que Haskell es muy inflexible, por lo que no puede simplemente asumir que los parámetros Int suministrados a su función de forma automática serán forzados a los números flotantes que las funciones de registro generalmente toman.

5

logBase se declara que funciona en tipos de coma flotante. Int no es un tipo de coma flotante y existe no automatic conversion in Haskell. Prueba esto:

-- Number of digits needed for the multiplication table n*n in base 'base' 
nOfDg :: Int -> Float -> Int 
nOfDg n base = 1 + floor (logBase base (fromIntegral (n*n))) 
+0

Supongo que también necesitará '(fromIntegral base)'. –

+0

@Jason: No con el tipo que Dan le dio a esa función, no lo harás. – Chuck

+0

Sí, depende de cómo quieras usarlo. O lo hago como si lo tuviera si está bien para cambiar la firma del tipo, o si no uso la versión de Andy. –

3

Desde el Preludio:

logBase :: Floating a => a -> a -> a 

Esto significa que el uso de logBase debe utilizar un tipo flotante. Pero Int no es un tipo flotante, y no hay conversión automática de tipos numéricos, por lo que hay que convertirlo de int a un tipo flotante:

nOfDg n base = 1 + floor (logBase (toEnum base) (toEnum n)) 

la función toEnum tomar un int como parámetro y devuelve un " Enum "tipo. La parte buena es que Float es una instancia de Enum, por lo que podría utilizarlo

toEnum :: Enum a => Int -> a 

Usted debe leer/a documentar sobre las clases de tipo estándar en Haskell para los tipos numéricos (Num, fraccional, Integral, flotante ...) ya que a menudo aparecen en el código, las conversiones de aprendizaje podrían ser útiles.

Editar: este Haskell Wiki Book proporciona un gráfico muy útil de la relación entre las clases de tipos de estándares, incluidos los tipos numéricos.

Cuestiones relacionadas