haskell - Haskell Fractional 无法推断 (RealFrac a) 由于使用“round”而产生
问题描述
我不想执行整数除法。我想采用小数输入类型,对其进行除法,将结果四舍五入为整数并返回。
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
意味着Real
和。意味着数字必须是一维的(与二维复数或更高维向量相反)。需要,因为它必须将其输入映射到一维整数集上。并且显然需要,否则舍入没有多大意义。所以,需要一个作为输入。更改为是第一个错误的正确解决方案。Fractional
Real
round
Real
round
Fractional
round
RealFrac
Fractional
RealFrac
第二个错误是因为您指定您的类型是Integral
,但随后您应用了fromInteger
需要具体的函数Integer
。您应该更改fromInteger
为fromIntegral
.
然后你仍然会得到一个错误,因为你写了fromInteger 2*k
,这意味着(fromInteger 2) * k
在 Haskell 中,但你可能是指fromInteger (2 * k)
or 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 感兴趣,那么选择更具体的类型可能更有意义,例如Double
orRational
代替RealFrac a => a
andInt
或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)
推荐阅读
- python - 在python中使用带有bluepy的BLE加速等待通知
- model - Laravel Eloquent 关系(3 表)
- ios - pkpass 文件在 Safari Mac 中打开但在 iPhone 上不打开
- r - 根据 r 中最近 3 个月的数据汇总数据
- python-3.x - 如何使用 Python 在 Splunk API 中为 oneshot 搜索设置 TTL?
- solr - solr - 使用尾随通配符搜索不会返回预期结果
- here-api - HERE Routing API 是否考虑流量数据?
- bash - 尝试验证 jq 命令输出等于字符串或字符串出现多次(AWS ELB 实例状态查询)
- javascript - 如何在 Web Worker 中使用 performance.memory API
- javascript - 有没有办法在一条sql语句中插入大量数据?