Search code examples
haskellghcmonomorphism-restriction

How can I fix this Monomorphism Restriction warning


When I load the following code in ghci I get a Monomomorphism restriction warning with the suggested fix of

 Consider giving ‘pexp’ and ‘nDividedByPExp’ a type signature
   |
17 |            (nDividedByPExp, pexp) = getPExp' nDividedByP 1

but doing that doesn't solve the problem. I then get the error:

Overloaded signature conflicts with monomorphism restriction
        nDividedByPExp :: Integral i => i

Here is the code:

{-# OPTIONS_GHC -Wall -fno-warn-incomplete-patterns #-}
{-# LANGUAGE ExplicitForAll, ScopedTypeVariables #-}

pfactor :: forall i. Integral i =>  i -> [(i, i)]
-- pfactor :: Integral i => i -> [(i, i)]
pfactor m =
   pf' m [] $ primesUpTo (floorSqrt m)
   where
     pf' :: Integral i => i -> [(i, i)] ->[i] -> [(i, i)]
     pf' n res (p : ps)
         | pIsNotAFactor = pf' n res ps     
         | otherwise = pf' nDividedByPExp ((p, pexp) : res) remainingPrimes
         where
           (nDividedByP, r)       = n `quotRem` p
           pIsNotAFactor          = r /= 0
           -- nDividedByPExp, pexp :: Integral i => i
           (nDividedByPExp, pexp) = getPExp' nDividedByP 1
           -- getPExp' :: Integral i => i -> i -> (i, i)
           getPExp' currNDividedByP currExp
               | pDoesNotDivideCurrNDividedByP   = (currNDividedByP, currExp)
               | otherwise                       = getPExp' q1 (currExp + 1)
               where
                 -- q1, r1 :: Integral i => i
                 (q1, r1)                      = currNDividedByP `quotRem` p
                 pDoesNotDivideCurrNDividedByP = r1 /= 0
           remainingPrimes = takeWhile (<= floorSqrt nDividedByPExp) ps

floorSqrt :: Integral i => i -> i
floorSqrt = undefined

primesUpTo :: Integral i => i -> [i]
primesUpTo = undefined

I tried adding the declaration in commented line 16 as suggested but that resulted in an error as I described above.

I've deleted some lines from the actual code to make it simpler. I don't expect the code above to run properly but I do expect it to compile without warnings. I don't understand how to fix the warning I am getting.


Solution

  • When you declare their types as nDividedByPExp, pexp :: Integral i => i, it'll be treated as nDividedByPExp, pexp :: forall i. Integral i => i. This i and the i declared at the top level will be different types even though you brought the latter to the scope using ScopedTypeVariables. Also, i is still polymorphic.

    You can declare it as nDividedByPExp, pexp :: i, where i refers to the i at the top level which is bound to a specific type so is monomorphic.