我正在尝试编写一个简单的函数来删除数字的最后一位数字并返回其余数字。
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中工作?
答案 0 :(得分:4)
将您的功能更改为
dropLastDigit :: (Integral b) => b -> b
dropLastDigit x = (quot x 10) * (floor $ logBase 10 (fromIntegral x))
您在GHCi中运行的代码并不完全相同。您已x
替换101
。对于x
类中的任何类型b
,函数中的b
已注释(按类型签名)为Integral
类型,但logBase
需要某些内容在Floating
班。
另一方面,文字101
的类型为Num a => a
,即它已重载并且可以在任何数字类型中使用。因此,GHCi可以在第一次出现时在类型Integer
上使用它,作为quot
的参数,在第二次出现时作为Double
使用它作为logBase
的参数。
答案 1 :(得分:3)
这不完全相同。您可以轻松查看:
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
实例一起使用。
话虽如此,你的功能并没有“丢弃”最后一位数字。如果您只想将12345
转换为1234
,则可以将dropLastDigit
简化为
dropLastDigit x = x `div` 10
但是,如果您想将12345
转换为12340
,则必须在之后乘以10:
dropLastDigit x = 10 * (x `div` 10)