[英]Haskell basic function definition problem
我正在學習Haskell,並且正在嘗試編寫一個函數以返回數字的因子列表。 這是我所擁有的:
factors :: Int -> [Int]
factors n = [x | x <- [2..s], n `mod` x == 0]
where s = floor (sqrt n)
當我嘗試在ghci
加載模塊時,出現兩個錯誤,
p003.hs:3:14:
No instance for (RealFrac Int)
arising from a use of `floor' at p003.hs:3:14-27
Possible fix: add an instance declaration for (RealFrac Int)
In the expression: floor (sqrt n)
In the definition of `s': s = floor (sqrt n)
In the definition of `factors':
factors n = [x | x <- [2 .. s], n `mod` x == 0]
where
s = floor (sqrt n)
p003.hs:3:21:
No instance for (Floating Int)
arising from a use of `sqrt' at p003.hs:3:21-26
Possible fix: add an instance declaration for (Floating Int)
In the first argument of `floor', namely `(sqrt n)'
In the expression: floor (sqrt n)
In the definition of `s': s = floor (sqrt n)
Failed, modules loaded: none.
有什么建議么?
該參數的類型為Int
,因此您無法為其計算平方根。 您首先需要將其轉換為浮點類型,可以使用fromIntegral進行處理。 與某些其他語言不同,Haskell不會自動將整數提升為浮點數(也不進行任何其他自動類型轉換)。
因此將sqrt n
更改為sqrt (fromIntegral n)
。
sqrt
函數的類型是
sqrt :: (Floating a) => a -> a
您可以在ghci中輸入:t sqrt
進行檢查。
Int
不是Floating
的實例,這就是為什么看到第二個錯誤的原因。
第一個錯誤的原因是相同的; 檢查:t floor
發現類型是:
floor :: (RealFrac a, Integral b) => a -> b
該函數需要RealFrac
的實例,並且您正在提供Int
。
鍵入:info RealFrac
或:info Floating
顯示這兩個都沒有Int
的實例,這就是為什么錯誤內容顯示為
沒有實例。
解決此問題的方法是確保類型正確。 它們必須是正確的類型類的成員。
一種簡單的方法是使用fromIntegral
函數,該函數:t
顯示類型為:
fromIntegral :: (Integral a, Num b) => a -> b
必須使用fromIntegral
,因為傳入類型為Int
,但是函數floor
和sqrt
分別對RealFrac
和Floating
類型進行操作。
之所以允許這樣做是因為,從類型簽名中可以看出, fromIntegral
返回Num
的實例,該實例同時包括RealFrac
和Floating
類型。 您可以通過在ghci中輸入:info Num
和:info Float
並查看輸出來說服自己。
對您的程序進行更改將得到以下最終結果,該結果應可以按您的意願工作:
factors :: Int -> [Int]
factors n = [x | x <- [2..s], n `mod` x == 0]
where s = floor (sqrt $ fromIntegral n)
Haskell教程的有關Type Classes和Numbers的部分提供了兩個很好的資源,可以准確地了解正在發生的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.