proyectos programas juegos hechos ejemplos haskell numbers type-conversion ghci

programas - problemas con conversiones de números triviales en Haskell



programas hechos en haskell (2)

Estoy intentando escribir una función trivial para soltar el último dígito de un número y devolver el resto del número.

dropLastDigit :: (Integral b) => b -> b dropLastDigit x = (quot x 10) * (floor $ logBase 10 x)

sin embargo, cuando intento cargar esto en ghci, obtengo:

Could not deduce (Floating b) arising from a use of ‘logBase’ from the context (Integral b) bound by the type signature for dropLastDigit :: Integral b => b -> b at haskelljokes.hs:6:18-39 Possible fix: add (Floating b) to the context of the type signature for dropLastDigit :: Integral b => b -> b In the second argument of ‘($)’, namely ‘logBase 10 x’ In the expression: floor $ logBase 10 x In an equation for ‘dropLastDigit’: dropLastDigit x = floor $ logBase 10 x

Sin embargo, ejecutar este código en ghci:

:t (quot 101 10) * (floor $ logBase 10 101)

produce: (quot 101 10) * (floor $ logBase 10 101) :: Integral a => a

Mi pregunta es, ¿qué estoy haciendo mal? ¿Y por qué (el código idéntico?) Trabaja en ghci?


Cambia tu función a

dropLastDigit :: (Integral b) => b -> b dropLastDigit x = (quot x 10) * (floor $ logBase 10 (fromIntegral x))

El código que estás ejecutando en GHCi no es idéntico. Usted ha reemplazado x por 101 . La x en su función fue anotada (por tipo de firma) para ser de tipo b para cualquier tipo b en la clase Integral , pero logBase necesita algo en la clase Floating .

Por otro lado, el literal 101 es de tipo Num a => a , es decir, está sobrecargado y se puede usar en cualquier tipo numérico. Entonces GHCi puede usarlo en tipo Integer en la primera aparición, como un argumento de quot , y como un Double en la segunda ocurrencia, como un argumento para logBase .


No es idéntico. Puedes verificar esto fácilmente:

ghci> let value101 = 101 :: Integral b => b ghci> let value10 = 10 :: Integral b => b ghci> (quot value101 value10) * (floor $ logBase value10 value101) <interactive>:7:28: Could not deduce (RealFrac s0) arising from a use of `floor'' from the context (Integral a) bound by the inferred type of it :: Integral a => a at <interactive>:7:1-60 The type variable `s0'' is ambiguous Note: there are several potential instances: instance RealFrac Double -- Defined in `GHC.Float'' instance RealFrac Float -- Defined in `GHC.Float'' instance Integral a => RealFrac (GHC.Real.Ratio a) -- Defined in `GHC.Real'' In the expression: floor In the second argument of `(*)'', namely `(floor $ logBase value10 value101)'' In the expression: (quot value101 value10) * (floor $ logBase value10 value101) -- even more...

El problema es que tanto 10 como 101 tienen el tipo Num a => a , independientemente de dónde los use. Así que logBase 10 101 usó con la instancia Fractional predeterminada ( Double ), mientras que quot usó con la instancia Integral predeterminada.

Dicho esto, su función no "suelta" el último dígito. Si solo quiere transformar 12345 a 1234 , puede simplificar dropLastDigit para

dropLastDigit x = x `div` 10

Si, sin embargo, desea transformar 12345 a 12340 , solo tiene que multiplicar por diez después:

dropLastDigit x = 10 * (x `div` 10)