我不想執行整數除法。我想接受一個小數輸入型別,用它做一個除法,將結果四舍五入為一個整數并回傳它。
piCalc :: (Fractional a, Ord a, Integral b) => a -> (a, b)
piCalc z = (piCalc' steps 1 0, steps)
where steps = round $ (4-z)/(2*z) 1
piCalc' :: (Integral a, Ord a, Fractional b) => a -> a -> a -> b
piCalc' 0 s k = 0
piCalc' steps s k = (fromInteger s*4)/(fromInteger 2*k 1) piCalc' (steps-1) ((-1)*s) (k 1)
main = do
print (piCalc 0.001)
我收到以下錯誤:
Recursion.hs:59:19: error:
* Could not deduce (RealFrac a) arising from a use of `round'
from the context: (Fractional a, Ord a, Integral b)
bound by the type signature for:
piCalc :: forall a b.
(Fractional a, Ord a, Integral b) =>
a -> (a, b)
at Recursion.hs:57:1-58
Possible fix:
add (RealFrac a) to the context of
the type signature for:
piCalc :: forall a b.
(Fractional a, Ord a, Integral b) =>
a -> (a, b)
* In the first argument of `($)', namely `round'
In the expression: round $ (4 - z) / (2 * z) 1
In an equation for `steps': steps = round $ (4 - z) / (2 * z) 1
|
59 | where steps = round $ (4-z)/(2*z) 1
| ^^^^^
Recursion.hs:63:34: error:
* Couldn't match expected type `Integer' with actual type `a'
`a' is a rigid type variable bound by
the type signature for:
piCalc' :: forall a b.
(Integral a, Ord a, Fractional b) =>
a -> a -> a -> b
at Recursion.hs:61:1-64
* In the first argument of `fromInteger', namely `s'
In the first argument of `(*)', namely `fromInteger s'
In the first argument of `(/)', namely `(fromInteger s * 4)'
* Relevant bindings include
k :: a (bound at Recursion.hs:63:17)
s :: a (bound at Recursion.hs:63:15)
steps :: a (bound at Recursion.hs:63:9)
piCalc' :: a -> a -> a -> b (bound at Recursion.hs:62:1)
|
63 | piCalc' steps s k = (fromInteger s*4)/(fromInteger 2*k 1) piCalc' (steps-1) ((-1)*s) (k 1)
| ^^^
在 piCalc(頂級函式)中將 Fractional 更改為 RealFrac 為我修復了第一個錯誤,但我不明白為什么或不知道這是否是一個“好”的解決方案。我在谷歌搜索時幾乎找不到任何 RealFrac 的使用示例。我不知道是什么導致了第二個錯誤。
uj5u.com熱心網友回復:
該RealFrac約束意味著雙方Real和Fractional。Real意味著數字必須是一維的(與二維復數或更高維的向量相反)。roundrequires Real,因為它必須將其輸入映射到一維整數集上。并且round顯然需要Fractional,否則四舍五入沒有多大意義。所以,round需要一個RealFrac作為輸入。更改Fractional為RealFrac是第一個錯誤的正確解決方案。
第二個錯誤是因為您指定您的型別是Integral,但隨后您應用了fromInteger需要具體Integer. 您應該更改fromInteger為fromIntegral.
然后你仍然會得到一個錯誤,因為你寫的是fromInteger 2*k,這意味著(fromInteger 2) * k在 Haskell 中,但你可能意味著fromInteger (2 * k)或2 * fromInteger k。這也應該改為fromIntegral.
此代碼編譯沒有錯誤:
piCalc :: (RealFrac a, Ord a, Integral b) => a -> (a, b)
piCalc z = (piCalc' steps 1 0, steps)
where steps = round $ (4-z)/(2*z) 1
piCalc' :: (Integral a, Ord a, Fractional b) => a -> a -> a -> b
piCalc' 0 s k = 0
piCalc' steps s k = (fromIntegral s*4)/(2 * fromIntegral k 1) piCalc' (steps-1) ((-1)*s) (k 1)
main = do
print (piCalc 0.001)
如果您只是對計算 pi 感興趣,那么選擇更具體的型別可能更有意義,例如DoubleorRational代替RealFrac a => aandInt或Integer代替Integral a => a。您可以保持實作不變,只更改簽名:
piCalc :: Double -> (Double, Int)
piCalc z = (piCalc' steps 1 0, steps)
where steps = round $ (4-z)/(2*z) 1
piCalc' :: Int -> Int -> Int -> Double
piCalc' 0 s k = 0
piCalc' steps s k = (fromIntegral s*4)/(2 * fromIntegral k 1) piCalc' (steps-1) ((-1)*s) (k 1)
main = do
print (piCalc 0.001)
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/316828.html
標籤:哈斯克尔
