dopatraman
dopatraman

Reputation: 13908

How to treat member of Num typeclass as an Int

This is a function I'm trying to write:

missingNumber :: (Num a) => [a] -> a
missingNumber list = (sum refList) - (sum list)
  where refList = [1..n]
        n = length list

Given a list of numbers, I want to sum them and compare them to a known list to see if any are missing. This code seems straightforward, but when I run it I get this (rather verbose) error:

Could not deduce (a ~ Int)
from the context (Num a)
  bound by the type signature for missingNumber :: Num a => [a] -> a
  at missingnumber.hs:1:18-36
  `a' is a rigid type variable bound by
      the type signature for missingNumber :: Num a => [a] -> a
      at missingnumber.hs:1:18
Expected type: [a]
  Actual type: [Int]
In the first argument of `sum', namely `refList'
In the first argument of `(-)', namely `(sum refList)'
In the expression: (sum refList) - (sum list)

I'm guessing this is happening because n in [1..n] must be an instance of the Enum type class in order to be iterated over in sequence. But (assuming I'm correct), how do I cast a as two types? Also... shouldn't Int be a member of the Num class?

Upvotes: 0

Views: 69

Answers (1)

Random Dev
Random Dev

Reputation: 52300

as you asked this should work:

missing :: (Num a, Foldable t) => t a -> a
missing xs = fromIntegral (sum [1..length xs + 1]) - sum xs

but only if your list of numbers is just missing one number in [1..m] for some m


your version don't work because you claim

missingNumber :: (Num a) => [a] -> a

and then it needs to work for all Num a - for example Double - but then you will mix Int with Double (for example) - which you cannot do

fromIntegral saves you here because it will bring back your Int into any Num a you might have there (it's fromIntegral :: (Integral c, Num d) => c -> d - here you have c ~ Int and d ~ a - where ~ means type-equality)

Upvotes: 1

Related Questions