Amateur
Amateur

Reputation: 49

extracting first two digits of a number haskell

I'm getting a frustrating error when I try to extract the first two digits of a number. First, I work out the length of digit using log, then I divide the number by the 10^(length of digit - 2) to extract the first two digits. The len and divisor functions work fine, but the firstTwo function fails, and I don't understand this because it seems so straight forward. I even tried adding {-# LANGUAGE FlexibleContexts #-}, but nothing. Please assist. Here's the code:

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

divisor n = 10 ^ (len n - 2)

firstTwo n = div n divisor

The error I get is:

Non type-variable argument in the constraint: 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

Upvotes: 0

Views: 1887

Answers (3)

Arthur Welf
Arthur Welf

Reputation: 176

  1. Convert your number to String.

  2. Check if the string contains 2 or more chars.

  3. If the check is successful, take first 2 chars from your string and convert them to Int (or put those chars in tuple or do with them whatever you want).

  4. Do something with the case if your number contains less than 2 digits (throw error for example).

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

Upvotes: 1

epsilonhalbe
epsilonhalbe

Reputation: 15967

As you seem to be a beginner my very first advice would be, to add type information as much as possible. At least for every top level (function) definition. This helps you, the compiler and everyone else reading your code understanding ​your intent.

Now to your problem: you try to divide a number n by a function divisor

div n (divisor n)

Should do the trick, well there is one small bit missing - logBase does not work on integers, while div does only work on integers. So you need to call fromInteger first to convert.

An alternative that would work with a small adjustment for negative numbers could be take 2 . show.

Upvotes: 3

Zeta
Zeta

Reputation: 105876

You use div on n and divisor, but divisor isn't the same type as n, it's a function. That's why you end up with Integral (r -> a).

Use firstTwo n = div n (divisor n), but keep in mind that logBase only works on Floating such as Double and Float, whereas div only works on Integral such as Integer and Int. Therefore, it will still not compile, unless you've changed len's type.

Add type signatures to your function to get better error messages.

Upvotes: 3

Related Questions