gpt4 book ai didi

Haskell 分数无法推断 (RealFrac a) 因使用 `round' 而产生

转载 作者:行者123 更新时间:2023-12-04 13:05:56 24 4
gpt4 key购买 nike

我不想进行整数除法。我想接受小数输入类型,对其进行除法,将结果四舍五入为整数并返回。

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 的任何使用示例。我不知道是什么导致了第二个错误。

最佳答案

RealFrac 约束意味着 RealFractionalReal 表示数字必须是一维的(与二维复数或更高维向量相反)。 round 需要 Real,因为它必须将其输入映射到一维整数集。而round显然需要Fractional,否则舍入意义不大。因此,round 需要一个 RealFrac 作为输入。将 Fractional 更改为 RealFrac 是第一个错误的正确解决方案。

第二个错误是因为您将类型指定为 Integer,但随后您应用了需要具体 IntegerfromInteger 函数。您应该将 fromInteger 更改为 fromIntegral

那么你仍然会报错,因为你写的是fromInteger 2*k,在Haskell中意思是(fromInteger 2) * k,但你的意思可能是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 感兴趣,那么选择更具体的类型可能更有意义,例如 DoubleRational 而不是 RealFrac a => aIntInteger 而不是 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)

关于Haskell 分数无法推断 (RealFrac a) 因使用 `round' 而产生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69503155/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com