提取数字haskell的前两位数字

时间:2017-04-18 06:29:46

标签: haskell

当我尝试提取数字的前两位数时,我遇到了令人沮丧的错误。首先,我使用log计算出数字的长度,然后我将数字除以10^(length of digit - 2)以提取前两位数字。 len和除数函数工作正常,但firstTwo函数失败,我不明白这一点,因为它似乎很直接。我甚至尝试添加{-# LANGUAGE FlexibleContexts #-},但没有。请协助。这是代码:

len n = (+) 1 $ truncate $ logBase 10 n -- length of a digit

divisor n = 10 ^ (len n - 2)

firstTwo n = div n divisor

我得到的错误是:

约束中的非类型变量参数:Integral (r -> a)

(Use FlexibleContexts to permit this)
When checking that ‘firstTwo’ has the inferred type
  firstTwo :: forall a r.
              (Floating r, Integral (r -> a), Num a, RealFrac r) =>
              (r -> a) -> r -> a

3 个答案:

答案 0 :(得分:3)

您在divn上使用divisor,但divisorn的类型不同,它是一个功能。这就是为什么你最终得到Integral (r -> a)

使用firstTwo n = div n (divisor n),但请注意,logBase仅适用于Floating,例如DoubleFloat,而div仅适用在Integral上,例如IntegerInt。因此,除非您更改了len的类型,否则它仍然无法编译。

为您的函数添加类型签名以获得更好的错误消息。

答案 1 :(得分:3)

由于您似乎是初学者,我的第一个建议是尽可能多地添加类型信息。至少对于每个顶级(功能)定义。这有助于您,编译器和阅读代码的其他人了解您的意图。

现在解决您的问题:您尝试将数字n除以函数divisor

div n (divisor n)

应该做的诀窍是,有一小部分缺失 - logBase对整数不起作用,而div只对整数有效。因此,您需要先致电fromInteger进行转换。

对负数进行小幅度调整的替代方法可能是take 2 . show

答案 2 :(得分:1)

  1. 将您的号码转换为字符串。

  2. 检查字符串是否包含2个或更多字符。

  3. 如果检查成功,请从字符串中取出前2个字符并将它们转换为Int(或将这些字符放在元组中,或者随意使用它们)。

  4. 如果您的号码少于2位数(例如抛出错误),请对案例做一些事情。

    firstTwo :: Integer -> Int
    firstTwo n
      | (length . show $ n) >= 2 = read . take 2 . show $ n
      | otherwise = error "The number contains less than 2 digits"