簡體   English   中英

Haskell sqrt類型錯誤

[英]Haskell sqrt type error

好的,所以我試圖編寫一個Haskell函數,該函數可以有效地檢測給定Int所有因素。 基於此問題中給出的解決方案,我得到了以下內容:

-- returns a list of the factors of n
factors         ::  Int -> [Int]
factors n       =   sort . nub $ fs where
                        fs  =   foldr (++) [] [[m,n `div` m] | m <- [1..lim+1], n `mod` m == 0]
                        lim =   sqrt . fromIntegral $ n

不幸的是,GHCi通知我在包含lim =等的行中No instance for (Floating Int)

我已經讀過這個答案 ,並且所提出的解決方案在直接鍵入GHCi時可以使用-它使我可以在Int上調用sqrt 但是,當在我的函數中放置看起來完全相同的代碼時,它將停止工作。

我是Haskell的新手,所以非常感謝您的幫助!

當您檢查sqrt的類型時

Prelude> :t sqrt 
sqrt :: Floating a => a -> a

它需要一個浮點數。 它在ghci中不起作用。 您可能曾嘗試在數字上調用它,而ghci會將類型推斷為Float。

Prelude> let a = 1 :: Int

Prelude> sqrt a

<interactive>:5:1:
    No instance for (Floating Int) arising from a use of `sqrt'
    Possible fix: add an instance declaration for (Floating Int)
    In the expression: sqrt a
    In an equation for `it': it = sqrt a

現在回到您的代碼。 問題出在表達式[1 .. lim + 1] 算術序列只能應用於Enum a => a類型的值。 由於lim的類型為Floating a => a ,因此您需要通過使用ceilingfloor將其轉換回Integral a => a 僅作為參考, Integral類實例也將類型限制為具有Enum實例。

您確實需要fromIntegral將(n :: Int)轉換為Double。 然后,您需要將從sqrt獲得的Double轉換回Int。 您將需要四舍五入,並且由於您使用(lim + 1)我可以看到您需要使用floor向下舍入:

isqrt :: Int -> Int
isqrt i = let d :: Double
              d = fromIntegral i
          in floor (sqrt d)

現在,您可以在代碼中使用它而不是sqrt。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM