[英]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
,因此您需要通過使用ceiling
或floor
將其轉換回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.