2015-11-09 28 views
1

我正在尝试编写一个简单的函数来删除数字的最后一位数字,并返回数字的其余部分。Haskell中的琐碎数字转换问题

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中工作?

回答

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... 

的问题是,无论10101有型Num a => a,无论在哪里使用它们。因此logBase 10 101使用它们与默认Fractional实例(Double),而quot使用它们与默认Integral实例。

这就是说,你的功能不会“删除”最后一位数字。如果你只是想变换123451234,您可以简化dropLastDigit

dropLastDigit x = x `div` 10 

如果,但是,想要改造1234512340,你只是必须在10点以后乘:

dropLastDigit x = 10 * (x `div` 10) 
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的参数。

+0

谢谢你明确的回应。真的有助于提醒我思考我的类型类。 Upvoted。泽塔击败你,所以他得到了接受。 –