Haskell 中的简单数字转换问题
problems with trivial number conversions in Haskell
我正在尝试编写一个简单的函数来删除数字的最后一位和 return 数字的其余部分。
dropLastDigit :: (Integral b) => b -> b
dropLastDigit x = (quot x 10) * (floor $ logBase 10 x)
但是,当我尝试将其加载到 ghci 中时,我得到:
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
然而,运行 ghci 中的这段代码:
:t (quot 101 10) * (floor $ logBase 10 101)
产生:(quot 101 10) * (floor $ logBase 10 101) :: Integral a => a
我的问题是,我做错了什么?为什么(相同的代码?)在 ghci 中工作?
将函数更改为
dropLastDigit :: (Integral b) => b -> b
dropLastDigit x = (quot x 10) * (floor $ logBase 10 (fromIntegral x))
您在 GHCi 中 运行 的代码不相同。您已将 x
替换为 101
。对于 Integral
class 中的任何类型 b
,函数中的 x
被注释(通过类型签名)为 b
类型,但是 logBase
Floating
class.
中需要一些东西
另一方面,字面值 101
是 Num a => a
类型,也就是说,它被重载并且可以用于任何数字类型。因此 GHCi 可以在第一次出现时以类型 Integer
使用它,作为 quot
的参数,并在第二次出现时作为 Double
作为 logBase
的参数。
不完全相同。您可以轻松查看:
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...
问题是 10
和 101
的类型都是 Num a => a
,无论您在哪里使用它们。因此 logBase 10 101
将它们与默认的 Fractional
实例 (Double
) 一起使用,而 quot
将它们与默认的 Integral
实例一起使用。
也就是说,您的函数没有 "drop" 最后一位。如果只想将12345
转化为1234
,可以将dropLastDigit
简化为
dropLastDigit x = x `div` 10
但是,如果您想要将 12345
转换为 12340
,则只需乘以 10:
dropLastDigit x = 10 * (x `div` 10)
我正在尝试编写一个简单的函数来删除数字的最后一位和 return 数字的其余部分。
dropLastDigit :: (Integral b) => b -> b
dropLastDigit x = (quot x 10) * (floor $ logBase 10 x)
但是,当我尝试将其加载到 ghci 中时,我得到:
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
然而,运行 ghci 中的这段代码:
:t (quot 101 10) * (floor $ logBase 10 101)
产生:(quot 101 10) * (floor $ logBase 10 101) :: Integral a => a
我的问题是,我做错了什么?为什么(相同的代码?)在 ghci 中工作?
将函数更改为
dropLastDigit :: (Integral b) => b -> b
dropLastDigit x = (quot x 10) * (floor $ logBase 10 (fromIntegral x))
您在 GHCi 中 运行 的代码不相同。您已将 x
替换为 101
。对于 Integral
class 中的任何类型 b
,函数中的 x
被注释(通过类型签名)为 b
类型,但是 logBase
Floating
class.
另一方面,字面值 101
是 Num a => a
类型,也就是说,它被重载并且可以用于任何数字类型。因此 GHCi 可以在第一次出现时以类型 Integer
使用它,作为 quot
的参数,并在第二次出现时作为 Double
作为 logBase
的参数。
不完全相同。您可以轻松查看:
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...
问题是 10
和 101
的类型都是 Num a => a
,无论您在哪里使用它们。因此 logBase 10 101
将它们与默认的 Fractional
实例 (Double
) 一起使用,而 quot
将它们与默认的 Integral
实例一起使用。
也就是说,您的函数没有 "drop" 最后一位。如果只想将12345
转化为1234
,可以将dropLastDigit
简化为
dropLastDigit x = x `div` 10
但是,如果您想要将 12345
转换为 12340
,则只需乘以 10:
dropLastDigit x = 10 * (x `div` 10)