代码之家  ›  专栏  ›  技术社区  ›  George Co

如何修复此单态性限制警告

  •  0
  • George Co  · 技术社区  · 2 年前

    当我在ghci中加载以下代码时,我会得到一个单态性限制警告,并建议修复

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

    但这样做并不能解决问题。然后我得到错误:

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

    这是代码:

    {-# 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
    

    我尝试按照建议在注释行16中添加声明,但这导致了如上所述的错误。

    我已经从实际代码中删除了一些行,使其更简单。我不希望上面的代码能正常运行,但我希望它能在编译时没有警告。我不知道如何解决我收到的警告。

    0 回复  |  直到 2 年前
        1
  •  4
  •   snak    2 年前

    当您将它们的类型声明为 nDividedByPExp, pexp :: Integral i => i ,将被视为 nDividedByPExp, pexp :: forall i. Integral i => i i 在顶层声明的将是不同的类型,即使您使用 ScopedTypeVariables 而且 仍然是多态的。

    您可以将其声明为 nDividedByPExp, pexp :: i 哪里 指的是 在与特定类型绑定的顶层,因此是单态的。

    推荐文章