gpt4 book ai didi

Haskell:Double 和 Int 之间的变量类型混淆

转载 作者:行者123 更新时间:2023-12-02 01:25:00 25 4
gpt4 key购买 nike

作为一个 uni 分配,我应该用类型声明编写一个函数:

pi_approx :: Int -> Double

这是我的第一次尝试:
pi_approx :: Int -> Double
pi_approx x = let total = sum [1 / (y^2) | y <- [1..x]]
in sqrt (6 * total)

这引发了以下错误:
pi_approx.hs:4:8: error:
* Couldn't match expected type `Double' with actual type `Int'
* In the expression: sqrt (6 * total)
In the expression:
let total = sum [1 / (y ^ 2) | y <- ...] in sqrt (6 * total)
In an equation for `pi_approx':
pi_approx x = let total = sum ... in sqrt (6 * total)
|
4 | in sqrt (6 * total)
| ^^^^^^^^^^^^^^^^

我一步一步地试图理解为什么解释器把它当作一个 Int:
level1 :: Fractional a => a -> a
level1 x = 1 / (x^2)

到目前为止,一切都很好。
level2 :: (Enum a, Fractional a) => a -> [a]
level2 x = [level1 y | y <- [1..x]]


也如预期。
level3 :: (Enum a, Fractional a) => a -> a
level3 x = sum (level2 x)

看不到 Int...
level4 :: (Enum a, Fractional a) => a -> a
level4 x = 6 * (level3 x)

最后
level5 :: (Floating a, Enum a) => a -> a
level5 x = sqrt (level4 x)

走下这个兔子洞后,我离我的答案更近了。我让它运行 fromIntegral
pi_approx :: Int -> Double
pi_approx x = let total = sum [(fromIntegral 1) / ((fromIntegral y)^ (fromIntegral 2)) | y <- [1..x]]
in sqrt (6*total)

但这让我更接近于理解是什么导致了第一个版本中的错误。有人可以解释我错过了什么吗?为什么是 sqrt (6*total)被视为 Int ?

最佳答案

由于类型类的类型检查方式,显示的类型错误并不是最有用的错误。

[ 1 / (y^2) | y <- [1..x] ]

所以这可能并不奇怪,因为 xInt , [1..x]Int 的列表s等 yInt . y^2 也不足为奇。是 Int . GHC 失去我们的地方是它决定 1 / (y^2)Int .

原因是这样的:除法运算符的类型是
(/) :: (Fractional a) => a -> a -> a

也就是说,它在两边都采用相同的类型,并且也返回它。所以只要类型 y^2已知为 Int , 我们推断 1整个表达式为 Int还。稍后,在约束检查阶段,GHC 将确保 IntFractional ,当然不是。例如:
recp :: Int -> Int
recp x = 1 / x

会给你一个更好的错误
• No instance for (Fractional Int) arising from a use of ‘/’
• In the expression: 1 / x
In an equation for ‘recp’: recp x = 1 / x

但是在检查您的功能时并没有那么远,因为首先出现了类型统一失败。

有时,如果您无法找出错误,删除签名并查看推断出的类型会很有帮助(通常,添加更多类型签名会有所帮助,但并非总是如此)
ghci> :t pi_approx
pi_approx :: (Floating a, Enum a) => a -> a

如果没有签名,该函数实际上会进行类型检查。它也有效:
ghci> pi_approx 100
3.1320765318091053

这里 100默认为 Double满足 Fractional约束,整个定义通过 Double s。

只是不接受 Int年代:
ghci> pi_approx (100 :: Int)

<interactive>:1:1: error:
• No instance for (Floating Int) arising from a use of ‘pi_approx’
• In the expression: pi_approx (1 :: Int)

关于Haskell:Double 和 Int 之间的变量类型混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61776855/

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