Haskell 哈斯凯尔分部,仍然是唐';我不明白
我还是不明白哈斯克尔的分工。我的第一个意图是定义这样一个函数:Haskell 哈斯凯尔分部,仍然是唐';我不明白,haskell,types,integer,int,division,Haskell,Types,Integer,Int,Division,我还是不明白哈斯克尔的分工。我的第一个意图是定义这样一个函数: piApprox :: (Integral a, Fractional b) => a -> b piApprox n = 4 * sum [ (-1)^k / (2*k + 1) | k <- [0..n] ] 但它再次引发了“无法推断”的错误 如果我在解释器中运行此代码以找出哪个签名是最好的,结果是: Prelude> let piApprox n = 4 * sum [ (-1)^k / (2*k +
piApprox :: (Integral a, Fractional b) => a -> b
piApprox n = 4 * sum [ (-1)^k / (2*k + 1) | k <- [0..n] ]
但它再次引发了“无法推断”的错误
如果我在解释器中运行此代码以找出哪个签名是最好的,结果是:
Prelude> let piApprox n = 4 * sum [ (-1)^k / (2*k + 1) | k <- [0..n] ]
Prelude> :t piApprox
piApprox :: (Fractional a, Integral a) => a -> a
这是可行的,但我认为这不是最好的方法
我还认为,即使输入和输出类型在签名中都是正确的,中间操作(-1)^k/(2*k+1)
——除法的位置——也可能是问题所在,因此我还定义了:
piApprox' :: (Fractional a) => Int -> a
piApprox' n = 4 * sum [ (fromIntegral) $ (-1)^k / (2*k + 1) | k <- [0..n] ]
piApprox':(分数a)=>Int->a
piApprox'n=4*sum[(fromIntegral)$(-1)^k/(2*k+1)| k您的问题是混合了不兼容的数字类型。您说过n是一些整数(具体来说,在本例中是整数)。k这应该可以:
piApprox n = 4 * sum [ fromIntegral ((-1)^k) / fromIntegral (2*k + 1) | k <- [0..n] ]
piApprox n=4*sum[from integral(-1)^k)/from integral(2*k+1)| ka->b
所以它基本上将整型转换为Num型
(/
)的类型为:
分数a=>a->a->a
,因此必须向其提供分数数据
fromIntegral
函数将通过将其转换为Num
类型来实现这一点,该类型包括分数类型。我主张此签名:
piApprox :: (Fractional a) => Int -> a
piApprox :: (Fractional r) => Int -> r
原因是,“precision”参数没有任何特定的“value”含义,它只是一个计数器,表示您愿意让函数运行多少步。(更好的方法可能是指定您希望允许的与真值π的偏差,而不是计算深度,但这更复杂。)
接下来,当前实现的冲突点实际上是(-1)^k
(它需要积分
,因为求幂是通过递归乘法实现的)是的,这是数学和科学中表示交替符号的常用方法,但如果你想一想,这是一种非常糟糕的方法。你对幂不感兴趣,只对符号交替感兴趣,而这在循环[1,-1]
中更自然地实现
对于乘法,它是不同的,它根本不需要整数
,但需要两个参数具有相同的类型。实现这一点的自然方法是,立即使用分数
变量,而不是从整数转换!因此,您可以使用[0..from Integral n]而不是[0..n]
。每一步只进行一次转换,而不是一次转换
实际上,最好不要绑定索引!因为这是Haskell,所以可以将列表定义为无限(就像cycle
也一样)。当然,不能对无限列表求和,但可以在执行此操作之前将其精简:
piApprox :: (Fractional r) => Int -> r
piApprox n = 4 * sum (take n [ σ / (2*k + 1) | (σ,k) <- zip (cycle [-1,1]) [0..] ])
这比您的实现少了一步,因为take n[0..]
相当于[0..n-1]
。我想这没什么大不了的,否则修复起来很简单
最后:我假设你知道这个公式在收敛速度方面非常糟糕!你可能是指整数而不是第一行代码上的整数。Haskell中没有自动转换类型,因此由于结果是b
类型,你需要转换a
一些在这里,例如,通过使用积分k
中的而不是k
“我们如何将Num
传递到fractive
”…这对于非OO语言来说是糟糕的措辞。您不能“传递Num
”,您可以传递恰好在Num
类型类中的类型的对象。Haskell没有子类型,这可能是您所指的。即使如此,它也需要以另一种方式传递:“传递分数到Num
”@leftaroundabout是的,我同意你的看法。你将如何更好地重新表述?我只想说“fromIntegral将整数转换为任何其他Num
类型(包括分数类型)的数字”。阅读各种类型的类是你可以在其他地方做的事情。@leftaroundabout,谢谢,我想重新表述得更好。
piApprox :: (Fractional r) => Int -> r
piApprox n = 4 * sum (take n [ σ / (2*k + 1) | (σ,k) <- zip (cycle [-1,1]) [0..] ])
piApprox n = (4 *) . sum $
take n [ σ / (2*k + 1) | σ <- cycle [1, -1]
| k <- [0..]
]