I'm still rather new to Haskell and I've encountered a problem that probably shouldn't be too hard to solve but totally stumped me.
I've written a function:
maxFor l n = n * m * (m + 1) / 2 where m = l `div` n
The function belongs to a small module which loads without problems, but throws two errors that are embarrassingly cryptic to me, whenever I try to use the function after loading the module:
<interactive>:182:1:
No instance for (Integral a0) arising from a use of `maxFor'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Integral Int -- Defined in `GHC.Real'
instance Integral Integer -- Defined in `GHC.Real'
instance Integral GHC.Types.Word -- Defined in `GHC.Real'
In the expression: maxFor 999 5
In an equation for `it': it = maxFor 999 5
<interactive>:182:8:
No instance for (Num a0) arising from the literal `999'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Num Double -- Defined in `GHC.Float'
instance Num Float -- Defined in `GHC.Float'
instance Integral a => Num (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus three others
In the first argument of `maxFor', namely `999'
In the expression: maxFor 999 5
In an equation for `it': it = maxFor 999 5
I understand it's telling me my function is missing a proper type declaration, but I don't understand how to write it without the compiler nagging again. I've tried countless variants and that I don't understand the actual problem doesn't help me to solve the problem.
Part of the problem might be that I'm using (/)
and div
in one function, so the needed type declaration will probably contain Fractional
and/or Integral
, since:
(/) :: Fractional a => a -> a -> a
and:
div :: Integral a => a -> a -> a
But that's as far as I've got and I'm stuck. How would I write the type declaration for maxFor
? What am I doing wrong? Am I missing or overlooking something that should be obvious?
Any help and constructive feedback is greatly appreciated.
EDIT: I've found this answer on stack overflow, which already helps a little. I'd still appreciate help, but I will of course delete the question, if it turns out I'm being an idiot and end up being downvoted.
Note: This post is written in literate Haskell . You can save it as Max.lhs and try it in your GHCi.
First of all, lets reason your use of (/2)
. Is the number n * m * (m + 1)
odd or even? Well, either m
is odd, and m + 1
is even, and therefore the whole product is even, or m
is even and the same arguments hold.
So instead of n * m * (m + 1) / 2
, we can use n * m * (m + 1) `div` 2
:
> maxFor l n = n * m * (m + 1) `div` 2
> where m = l `div` n
Now, all we have to to is to check the types of the functions we use:
(+) :: Num a => a -> a -> a
(*) :: Num a => a -> a -> a
div :: Integral n => n -> n -> n
And that leads directly to your type:
> maxFor :: Integral n => n -> n -> n
Alternatively, you can use some specific type to get errors out:
maxFor :: Integer -> Integer -> Integer
-- Now GHC yells at you since Integer doesn't have a Fractional instance
-- and you try to use (/).
You've already recognized the problem. div
indicates that l
and n
are some integral types, but (/)
indicates that they're fractional. In your usual Prelude
, there is no data type that's an instance of both typeclasses. You can check this in GHCi:
Prelude> :info Fractional
class Num a => Fractional a where
(/) :: a -> a -> a
recip :: a -> a
fromRational :: Rational -> a
-- Defined in ‘GHC.Real’
instance Fractional Float -- Defined in ‘GHC.Float’
instance Fractional Double -- Defined in ‘GHC.Float’
Prelude> :info Integral
class (Real a, Enum a) => Integral a where
quot :: a -> a -> a
rem :: a -> a -> a
div :: a -> a -> a
mod :: a -> a -> a
quotRem :: a -> a -> (a, a)
divMod :: a -> a -> (a, a)
toInteger :: a -> Integer
-- Defined in ‘GHC.Real’
instance Integral Word -- Defined in ‘GHC.Real’
instance Integral Integer -- Defined in ‘GHC.Real’
instance Integral Int -- Defined in ‘GHC.Real’
This is the first part.
The second part stems from literals. 999
or 5
has type Num a => a
. Now GHC is between a rock and a hard place: it has to find a Num
instance, that's both Integral
and Fractional
. Since there's no such type (see above), GHC gives up due to ambiguity. You can check this too in GHCi:
Prelude> 5 :: Num a => a
5
Prelude> 5 :: (Fractional a, Integral a) => a
<interactive>:7:1:
No instance for (Fractional a0) arising from a use of ‘it’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Integral a => Fractional (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance Fractional Double -- Defined in ‘GHC.Float’
instance Fractional Float -- Defined in ‘GHC.Float’
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
So this is mainly the reason why you end up with the error.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.